summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Help/manual/cmake-gui.1.rst5
-rw-r--r--Help/manual/cmake.1.rst368
-rw-r--r--Help/release/dev/cmake-presets.rst5
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/QtDialog/CMakeLists.txt8
-rw-r--r--Source/QtDialog/CMakeSetup.cxx25
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx86
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h12
-rw-r--r--Source/QtDialog/CMakeSetupDialog.ui23
-rw-r--r--Source/QtDialog/FirstConfigure.cxx54
-rw-r--r--Source/QtDialog/FirstConfigure.h15
-rw-r--r--Source/QtDialog/QCMake.cxx160
-rw-r--r--Source/QtDialog/QCMake.h23
-rw-r--r--Source/QtDialog/QCMakePreset.cxx50
-rw-r--r--Source/QtDialog/QCMakePreset.h30
-rw-r--r--Source/QtDialog/QCMakePresetComboBox.cxx64
-rw-r--r--Source/QtDialog/QCMakePresetComboBox.h35
-rw-r--r--Source/QtDialog/QCMakePresetItemModel.cxx143
-rw-r--r--Source/QtDialog/QCMakePresetItemModel.h45
-rw-r--r--Source/cmCMakePresetsFile.cxx763
-rw-r--r--Source/cmCMakePresetsFile.h141
-rw-r--r--Source/cmGlobalGeneratorFactory.h4
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx4
-rw-r--r--Source/cmGlobalVisualStudioVersionedGenerator.cxx6
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx3
-rw-r--r--Source/cmJSONHelpers.h11
-rw-r--r--Source/cmake.cxx343
-rw-r--r--Source/cmake.h56
-rw-r--r--Source/cmakemain.cxx7
-rw-r--r--Tests/CMakeGUI/CMakeGUITest.cmake38
-rw-r--r--Tests/CMakeGUI/CMakeGUITest.cxx267
-rw-r--r--Tests/CMakeGUI/CMakeGUITest.h3
-rw-r--r--Tests/CMakeGUI/CMakeLists.txt21
-rw-r--r--Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx80
-rw-r--r--Tests/CMakeGUI/QCMakePresetComboBoxTest.h13
-rw-r--r--Tests/CMakeGUI/QCMakePresetItemModelTest.cxx162
-rw-r--r--Tests/CMakeGUI/QCMakePresetItemModelTest.h17
-rw-r--r--Tests/CMakeGUI/QCMakePresetTest.cxx82
-rw-r--r--Tests/CMakeGUI/QCMakePresetTest.h14
-rw-r--r--Tests/CMakeGUI/presetArg-noPresetBinaryChange/CMakePresets.json.in33
-rw-r--r--Tests/CMakeGUI/presetArg-preset/CMakePresets.json.in33
-rw-r--r--Tests/CMakeGUI/presetArg-presetBinary/CMakePresets.json.in33
-rw-r--r--Tests/CMakeGUI/presetArg-presetBinaryChange/CMakePresets.json.in39
-rw-r--r--Tests/CMakeGUI/presetArg-presetConfigExists/CMakeLists.txt.in2
-rw-r--r--Tests/CMakeGUI/presetArg-presetConfigExists/CMakePresets.json.in33
-rw-r--r--Tests/CMakeGUI/presetArg-presetConfigExists/CMakeSetup.ini.in2
-rw-r--r--Tests/CMakeLib/testJSONHelpers.cxx35
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-stderr.txt11
-rw-r--r--Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-stderr.txt11
-rw-r--r--Tests/RunCMake/CMakePresets/CMakeLists.txt.in4
-rw-r--r--Tests/RunCMake/CMakePresets/CMakePresets.json.in481
-rw-r--r--Tests/RunCMake/CMakePresets/CacheOverride.cmake2
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance0-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance0.json.in13
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance1-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance1.json.in21
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance2-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/CyclicInheritance2.json.in29
-rw-r--r--Tests/RunCMake/CMakePresets/Debug-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/Debug-stdout.txt4
-rw-r--r--Tests/RunCMake/CMakePresets/Debug.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/Debug.json.in19
-rw-r--r--Tests/RunCMake/CMakePresets/DebugBase.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/DisableWarningFlags.cmake1
-rw-r--r--Tests/RunCMake/CMakePresets/DuplicatePresets-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/DuplicatePresets.json.in15
-rw-r--r--Tests/RunCMake/CMakePresets/EmptyPresetName-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/EmptyPresetName.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/EnvCycle-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorDeprecated-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorDeprecated-stderr.txt7
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorDeprecated.cmake1
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorDev-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt8
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorDev.cmake1
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated.json.in16
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorNoWarningDev-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ErrorNoWarningDev.json.in16
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraPresetField-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraPresetField.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraRootField-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraRootField.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraVariableField-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ExtraVariableField.json.in16
-rw-r--r--Tests/RunCMake/CMakePresets/Good-stdout.txt46
-rw-r--r--Tests/RunCMake/CMakePresets/Good.cmake45
-rw-r--r--Tests/RunCMake/CMakePresets/GoodBOM.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/GoodBOM.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/GoodBinaryCmdLine.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/GoodBinaryRelative.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodBinaryUp.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/GoodGeneratorCmdLine.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInheritanceChild.cmake6
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInheritanceMacro.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInheritanceMulti.cmake10
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInheritanceMultiSecond.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInheritanceOverride.cmake18
-rw-r--r--Tests/RunCMake/CMakePresets/GoodInheritanceParent.cmake6
-rw-r--r--Tests/RunCMake/CMakePresets/GoodNoArgs.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/GoodNoS.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/GoodSpaces.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/GoodUserFromMain.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/GoodUserFromMain.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/GoodUserFromMainUser.json.in4
-rw-r--r--Tests/RunCMake/CMakePresets/GoodUserFromUser.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/GoodUserFromUser.json.in4
-rw-r--r--Tests/RunCMake/CMakePresets/GoodUserFromUserUser.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/GoodUserOnly.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/GoodUserOnlyUser.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/GoodWindowsBackslash.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/HighVersion-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/HighVersion-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/HighVersion.json.in4
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidGenerator-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidGenerator-stderr.txt3
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-stderr.txt3
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidInheritance-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidInheritance.json.in13
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetGenerator-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetGenerator-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetGenerator.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetName-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetName-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetName.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetVendor-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetVendor-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresetVendor.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresets-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresets-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidPresets.json.in4
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidRoot-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidRoot.json.in1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVariableValue-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVariableValue-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVariableValue.json.in15
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVariables-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVariables-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVariables.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVendor-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVendor-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVendor.json.in5
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVersion-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVersion-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/InvalidVersion.json.in4
-rw-r--r--Tests/RunCMake/CMakePresets/JSONParseError-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/JSONParseError.json.in0
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresets-stdout.txt6
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresets.json.in36
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsHidden-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsHidden-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt6
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt6
-rw-r--r--Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt6
-rw-r--r--Tests/RunCMake/CMakePresets/LowVersion-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/LowVersion-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/LowVersion.json.in4
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredEmpty.cmake0
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredEmpty.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredInvalid.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredMajor-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredMajor-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredMajor.json.in13
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredMinor-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredMinor-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredMinor.json.in14
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredPatch-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredPatch-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/MinimumRequiredPatch.json.in15
-rw-r--r--Tests/RunCMake/CMakePresets/NoCMakePresets-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoCMakePresets-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoDebug-stdout.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoDebug.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetArgument-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetBinaryDir-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetBinaryDir-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetBinaryDir.json.in9
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetGenerator-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetGenerator-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetGenerator.json.in9
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetName-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetName-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresetName.json.in9
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresets-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresets-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresets-stdout.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoPresets.json.in3
-rw-r--r--Tests/RunCMake/CMakePresets/NoSuchMacro-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoSuchPreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoSuchPreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoVariableValue-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoVariableValue-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoVariableValue.json.in13
-rw-r--r--Tests/RunCMake/CMakePresets/NoVersion-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/NoVersion-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/NoVersion.json.in3
-rw-r--r--Tests/RunCMake/CMakePresets/NoWarningFlags-stderr.txt23
-rw-r--r--Tests/RunCMake/CMakePresets/NoWarningFlags.cmake1
-rw-r--r--Tests/RunCMake/CMakePresets/PresetNotObject-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/PresetNotObject-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/PresetNotObject.json.in6
-rw-r--r--Tests/RunCMake/CMakePresets/RunCMakeTest.cmake212
-rw-r--r--Tests/RunCMake/CMakePresets/TestVariable.cmake25
-rw-r--r--Tests/RunCMake/CMakePresets/UnclosedMacro-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in11
-rw-r--r--Tests/RunCMake/CMakePresets/UseHiddenPreset-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/UseHiddenPreset-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/UserDuplicateCross-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/UserDuplicateCross-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/UserDuplicateCross.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/UserDuplicateCrossUser.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/UserDuplicateInUser-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/UserDuplicateInUser-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/UserDuplicateInUserUser.json.in15
-rw-r--r--Tests/RunCMake/CMakePresets/UserInheritance-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/UserInheritance-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/UserInheritance.json.in13
-rw-r--r--Tests/RunCMake/CMakePresets/UserInheritanceUser.json.in10
-rw-r--r--Tests/RunCMake/CMakePresets/VariableNotObject-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/VariableNotObject-stderr.txt2
-rw-r--r--Tests/RunCMake/CMakePresets/VariableNotObject.json.in13
-rw-r--r--Tests/RunCMake/CMakePresets/VendorMacro-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/VendorMacro-stderr.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioGeneratorArch-result.txt1
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioGeneratorArch-stderr.txt5
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioInheritanceChild.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioInheritanceMulti.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioInheritanceMultiSecond.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioInheritanceOverride.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioInheritanceParent.cmake4
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioToolset.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioToolsetOverride.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioWin32.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioWin32Override.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/VisualStudioWin64.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/WarningFlags-stderr.txt34
-rw-r--r--Tests/RunCMake/CMakePresets/WarningFlags.cmake1
-rw-r--r--Tests/RunCMake/CMakePresets/Warnings.json.in50
-rw-r--r--Tests/RunCMake/CMakePresets/WarningsBase.cmake3
-rw-r--r--Tests/RunCMake/CMakePresets/main.c4
-rw-r--r--Tests/RunCMake/CommandLine/NoArgs-stdout.txt1
280 files changed, 5185 insertions, 83 deletions
diff --git a/.gitignore b/.gitignore
index 1a257d2..2f35615 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
*.pyc
Testing
+CMakeUserPresets.json
# Visual Studio work directory
.vs/
diff --git a/Help/manual/cmake-gui.1.rst b/Help/manual/cmake-gui.1.rst
index ff8311b..d9c8ed7 100644
--- a/Help/manual/cmake-gui.1.rst
+++ b/Help/manual/cmake-gui.1.rst
@@ -11,6 +11,7 @@ Synopsis
cmake-gui [<options>]
cmake-gui [<options>] {<path-to-source> | <path-to-existing-build>}
cmake-gui [<options>] -S <path-to-source> -B <path-to-build>
+ cmake-gui [<options>] -S <path-to-source> --preset=<preset-name>
Description
===========
@@ -36,6 +37,10 @@ Options
If the directory doesn't already exist CMake will make it.
+``--preset=<preset-name>``
+ Name of the preset to use from the project's ``CMakePresets.json`` file, if it
+ has one.
+
.. include:: OPTIONS_HELP.txt
See Also
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 9850116..764f61e 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -12,6 +12,7 @@ Synopsis
cmake [<options>] <path-to-source>
cmake [<options>] <path-to-existing-build>
cmake [<options>] -S <path-to-source> -B <path-to-build>
+ cmake [<options>] -S <path-to-source> --preset=<preset-name>
`Build a Project`_
cmake --build <dir> [<options>] [-- <build-tool-options>]
@@ -148,6 +149,368 @@ source and build trees and generate a buildsystem:
$ cmake -S src -B build
+``cmake [<options>] -S <path-to-source> --preset=<preset-name>``
+ Uses ``<path-to-source>`` as the source tree and reads a preset from
+ ``<path-to-source>/CMakePresets.json`` and
+ ``<path-to-source>/CMakeUserPresets.json``. The preset specifies the
+ generator and the build directory, and optionally a list of variables and
+ other arguments to pass to CMake. The :manual:`CMake GUI <cmake-gui(1)>` can
+ also recognize ``CMakePresets.json`` and ``CMakeUserPresets.json`` files.
+
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` have exactly the same
+ format, and both are optional (though at least one must be present if
+ ``--preset`` is specified.) ``CMakePresets.json`` is meant to save
+ project-wide builds, while ``CMakeUserPresets.json`` is meant for developers
+ to save their own local builds. ``CMakePresets.json`` may be checked into a
+ version control system, and ``CMakeUserPresets.json`` should NOT be checked
+ in. For example, if a project is using Git, ``CMakePresets.json`` may be
+ tracked, and ``CMakeUserPresets.json`` should be added to the ``.gitignore``.
+
+ The presets are read before all other command line options. The options
+ specified by the 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.
+
+ The files are a JSON document with an object as the root:
+
+ .. code-block:: json
+
+ {
+ "version": 1,
+ "cmakeMinimumRequired": {
+ "major": 3,
+ "minor": 19,
+ "patch": 0
+ },
+ "configurePresets": [
+ {
+ "name": "default",
+ "displayName": "Default Config",
+ "description": "Default build using Ninja generator",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build/default",
+ "cacheVariables": [
+ {
+ "name": "MY_CACHE_VARIABLE",
+ "type": "BOOL",
+ "value": "OFF"
+ }
+ ]
+ }
+ ]
+ }
+
+ The root object recognizes the following fields:
+
+ ``version``
+
+ A required integer representing the version of the JSON schema. Currently,
+ the only supported version is 1.
+
+ ``cmakeMinimumRequired``
+
+ An optional object representing the minimum version of CMake needed to
+ build this project. This object consists of the following fields:
+
+ ``major``
+
+ An optional integer representing the major version.
+
+ ``minor``
+
+ An optional integer representing the minor version.
+
+ ``patch``
+
+ An optional integer representing the patch version.
+
+ ``vendor``
+
+ An optional map containing vendor-specific information. CMake does not
+ interpret the contents of this field except to verify that it is a map if
+ it does exist. However, the keys should be a vendor-specific domain name
+ followed by a ``/``-separated path. For example, the Example IDE 1.0 could
+ use ``example.com/ExampleIDE/1.0``. The value of each field can be anything
+ desired by the vendor, though will typically be a map. For example:
+
+ .. code-block:: json
+
+ {
+ "version": 1,
+ "vendor": {
+ "example.com/ExampleIDE/1.0": {
+ "autoFormat": true
+ }
+ },
+ "configurePresets": []
+ }
+
+ ``configurePresets``
+
+ An optional array of configure preset objects. Each preset may contain the
+ following fields:
+
+ ``name``
+
+ A required string representing the machine-friendly name of the preset.
+ This identifier is used in the ``--preset`` argument. There must not be
+ two presets in the union of ``CMakePresets.json`` and
+ ``CMakeUserPresets.json`` in the same directory with the same name.
+
+ ``hidden``
+
+ An optional boolean specifying whether or not a preset should be hidden.
+ If a preset is hidden, it cannot be used in the ``--preset=`` argument,
+ will not show up in the :manual:`CMake GUI <cmake-gui(1)>`, and does not
+ have to have a valid ``generator`` or ``binaryDir``, even from
+ inheritance. ``hidden`` presets are intended to be used as a base for
+ other presets to inherit via the ``inherits`` field.
+
+ ``inherits``
+
+ An optional array of strings representing the names of presets to inherit
+ from. The preset will inherit all of the fields from the ``inherits``
+ presets by default (except ``name``, ``hidden``, ``inherits``,
+ ``description``, and ``longDescription``), but can override them as
+ desired. If multiple ``inherits`` presets provide conflicting values for
+ the same field, the earlier preset in the ``inherits`` list will be
+ preferred. Presets in ``CMakePresets.json`` may not inherit from presets
+ in ``CMakeUserPresets.json``.
+
+ This field can also be a string, which is equivalent to an array
+ containing one string.
+
+ ``vendor``
+
+ An optional map containing vendor-specific information. CMake does not
+ interpret the contents of this field except to verify that it is a map
+ if it does exist. However, it should follow the same conventions as the
+ root-level ``vendor`` field. If vendors use their own per-preset
+ ``vendor`` field, they should implement inheritance in a sensible manner
+ when appropriate.
+
+ ``displayName``
+
+ An optional string with a human-friendly name of the preset.
+
+ ``description``
+
+ An optional string with a human-friendly description of the preset.
+
+ ``generator``
+
+ An optional string representing the generator to use for the preset. If
+ ``generator`` is not specified, it must be inherited from the
+ ``inherits`` preset (unless this preset is ``hidden``).
+
+ Note that for Visual Studio generators, unlike in the command line ``-G``
+ argument, you cannot include the platform name in the generator name. Use
+ the ``architecture`` field instead.
+
+ ``architecture``
+
+ An optional string representing the platform name to use for Visual
+ Studio generators.
+
+ ``toolset``
+
+ An optional string representing the toolset name to use for Visual Studio
+ generators.
+
+ ``cmakeGeneratorConfig``
+
+ An optional string telling CMake how to handle the ``architecture`` and
+ ``toolset`` fields. Valid values are:
+
+ ``"default"``
+
+ Set the platform and toolset using the ``architecture`` and ``toolset``
+ fields respectively. On non-Visual Studio generators, this will result
+ in an error if ``architecture`` or ``toolset`` are set.
+
+ ``"ignore"``
+
+ Do not set the platform or toolset at all, even on Visual Studio
+ generators. This is useful if, for example, a preset uses the Ninja
+ generator, and an IDE knows how to set up the Visual C++ environment
+ from the ``architecture`` and ``toolset`` fields. In that case, CMake
+ will ignore ``architecture`` and ``toolset``, but the IDE can use them
+ to set up the environment before invoking CMake.
+
+ ``binaryDir``
+
+ An optional string representing the path to the output binary directory.
+ This field supports macro expansion. If a relative path is specified, it
+ is calculated relative to the source directory. If ``binaryDir`` is not
+ specified, it must be inherited from the ``inherits`` preset (unless this
+ preset is ``hidden``).
+
+ ``cmakeExecutable``
+
+ An optional string representing the path to the CMake executable to use
+ for this preset. This is reserved for use by IDEs, and is not used by
+ CMake itself. IDEs that use this field should expand any macros in it.
+
+ ``cacheVariables``
+
+ An optional map of cache variables. The key is the variable name, and the
+ value is either ``null``, a string representing the value of the variable
+ (which supports macro expansion), or an object with the following fields:
+
+ ``type``
+
+ An optional string representing the type of the variable.
+
+ ``value``
+
+ A required string representing the value of the variable. This field
+ supports macro expansion.
+
+ Cache variables are inherited through the ``inherits`` field, and the
+ preset's variables will be the union of its own ``cacheVariables`` and
+ the ``cacheVariables`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+
+ ``environment``
+
+ An optional map of environment variables. The key is the variable name,
+ and the value is either ``null`` or a string representing the value of
+ the variable. Each variable is set regardless of whether or not a value
+ was given to it by the process's environment. This field supports macro
+ expansion, and environment variables in this map may reference each
+ other, and may be listed in any order, as long as such references do not
+ cause a cycle (for example, if ``ENV_1`` is ``$env{ENV_2}``, ``ENV_2``
+ may not be ``$env{ENV_1}``.)
+
+ Environment variables are inherited through the ``inherits`` field, and
+ the preset's environment will be the union of its own ``environment`` and
+ the ``environment`` from all its parents. If multiple presets in this
+ union define the same variable, the standard rules of ``inherits`` are
+ applied. Setting a variable to ``null`` causes it to not be set, even if
+ a value was inherited from another preset.
+
+ ``warnings``
+
+ An optional object specifying warnings. The object may contain the
+ following fields:
+
+ ``dev``
+
+ An optional boolean. Equivalent to passing ``-Wdev`` or ``-Wno-dev``
+ on the command line. This may not be set to ``false`` if ``errors.dev``
+ is set to ``true``.
+
+ ``deprecated``
+
+ An optional boolean. Equivalent to passing ``-Wdeprecated`` or
+ ``-Wno-deprecated`` on the command line. This may not be set to
+ ``false`` if ``errors.deprecated`` is set to ``true``.
+
+ ``uninitialized``
+
+ An optional boolean. Setting this to ``true`` is equivalent to passing
+ ``--warn-uninitialized`` on the command line.
+
+ ``unusedVars``
+
+ An optional boolean. Setting this to ``false`` is equivalent to passing
+ ``--no-warn-unused-cli`` on the command line.
+
+ ``systemVars``
+
+ An optional boolean. Setting this to ``true`` is equivalent to passing
+ ``--check-system-vars`` on the command line.
+
+ ``errors``
+
+ An optional object specifying errors. The object may contain the
+ following fields:
+
+ ``dev``
+
+ An optional boolean. Equivalent to passing ``-Werror=dev`` or
+ ``-Wno-error=dev`` on the command line. This may not be set to ``true``
+ if ``warnings.dev`` is set to ``false``.
+
+ ``deprecated``
+
+ An optional boolean. Equivalent to passing ``-Werror=deprecated`` or
+ ``-Wno-error=deprecated`` on the command line. This may not be set to
+ ``true`` if ``warnings.deprecated`` is set to ``false``.
+
+ As mentioned above, some fields support macro expansion. Macros are
+ recognized in the form ``$<macro-namespace>{<macro-name>}``. All macros are
+ evaluated in the context of the preset being used, even if the macro is in a
+ field that was inherited from another preset. For example, if the ``Base``
+ preset sets variable ``PRESET_NAME`` to ``${presetName}``, and the
+ ``Derived`` preset inherits from ``Base``, ``PRESET_NAME`` will be set to
+ ``Derived``.
+
+ It is an error to not put a closing brace at the end of a macro name. For
+ example, ``${sourceDir`` is invalid. A dollar sign (``$``) followed by
+ anything other than a left curly brace (``{``) with a possible namespace is
+ interpreted as a literal dollar sign.
+
+ Recognized macros include:
+
+ ``${sourceDir}``
+
+ Path to the project source directory.
+
+ ``${sourceParentDir}``
+
+ Path to the project source directory's parent directory.
+
+ ``${presetName}``
+
+ Name specified in the preset's ``name`` field.
+
+ ``${generator}``
+
+ Generator specified in the preset's ``generator`` field.
+
+ ``${dollar}``
+
+ A literal dollar sign (``$``).
+
+ ``$env{<variable-name>}``
+
+ Environment variable with name ``<variable-name>``. If the variable is
+ defined in the ``environment`` field, that value is used instead of the
+ value from the parent environment. If the environment variable is not
+ defined, this evaluates as an empty string.
+
+ Note that while Windows environment variable names are case-insensitive,
+ variable names within a preset are still case-sensitive. This may lead to
+ unexpected results when using inconsistent casing. For best results, keep
+ the casing of environment variable names consistent.
+
+ ``$penv{<variable-name>}``
+
+ Similar to ``$env{<variable-name>}``, except that the value only comes from
+ the parent environment, and never from the ``environment`` field. This
+ allows you to prepend or append values to existing environment variables.
+ For example, setting ``PATH`` to ``/path/to/ninja/bin:$penv{PATH}`` will
+ prepend ``/path/to/ninja/bin`` to the ``PATH`` environment variable. This
+ is needed because ``$env{<variable-name>}`` does not allow circular
+ references.
+
+ ``$vendor{<macro-name>}``
+
+ An extension point for vendors to insert their own macros. CMake will not
+ be able to use presets which have a ``$vendor{<macro-name>}`` macro, and
+ effectively ignores such presets. However, it will still be able to use
+ other presets from the same file.
+
+ CMake does not make any attempt to interpret ``$vendor{<macro-name>}``
+ macros. However, to avoid name collisions, IDE vendors should prefix
+ ``<macro-name>`` with a very short (preferably <= 4 characters) vendor
+ identifier prefix, followed by a ``.``, followed by the macro name. For
+ example, the Example IDE could have ``$vendor{xide.ideInstallDir}``.
+
In all cases the ``<options>`` may be zero or more of the `Options`_ below.
After generating a buildsystem one may use the corresponding native
@@ -813,6 +1176,11 @@ with one of the following options:
.. include:: OPTIONS_HELP.txt
+To view the presets available for a project, use
+
+.. code-block::shell
+
+ cmake <source-dir> --list-presets
See Also
========
diff --git a/Help/release/dev/cmake-presets.rst b/Help/release/dev/cmake-presets.rst
new file mode 100644
index 0000000..a901f10
--- /dev/null
+++ b/Help/release/dev/cmake-presets.rst
@@ -0,0 +1,5 @@
+cmake-presets
+-------------
+
+* :manual:`cmake(1)` and :manual:`cmake-gui(1)` now recognize
+ ``CMakePresets.json`` and ``CMakeUserPresets.json`` files.
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index d0d9459..1e16e17 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -184,6 +184,8 @@ set(SRCS
cmCLocaleEnvironmentScope.cxx
cmCMakePath.h
cmCMakePath.cxx
+ cmCMakePresetsFile.cxx
+ cmCMakePresetsFile.h
cmCommandArgumentParserHelper.cxx
cmCommonTargetGenerator.cxx
cmCommonTargetGenerator.h
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 5fd0e89..394762a 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -92,6 +92,12 @@ set(SRCS
QCMake.h
QCMakeCacheView.cxx
QCMakeCacheView.h
+ QCMakePreset.cxx
+ QCMakePreset.h
+ QCMakePresetComboBox.cxx
+ QCMakePresetComboBox.h
+ QCMakePresetItemModel.cxx
+ QCMakePresetItemModel.h
QCMakeWidgets.cxx
QCMakeWidgets.h
RegexExplorer.cxx
@@ -116,6 +122,8 @@ qt5_wrap_cpp(MOC_SRCS
FirstConfigure.h
QCMake.h
QCMakeCacheView.h
+ QCMakePresetComboBox.h
+ QCMakePresetItemModel.h
QCMakeWidgets.h
RegexExplorer.h
WarningMessagesDialog.h
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index 37c1f15..a5b2f34 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -32,7 +32,8 @@ static const char* cmDocumentationUsage[][2] = {
" cmake-gui [options]\n"
" cmake-gui [options] <path-to-source>\n"
" cmake-gui [options] <path-to-existing-build>\n"
- " cmake-gui [options] -S <path-to-source> -B <path-to-build>\n" },
+ " cmake-gui [options] -S <path-to-source> -B <path-to-build>\n"
+ " cmake-gui [options] -S <path-to-source> --preset=<preset-name>\n" },
{ nullptr, nullptr }
};
@@ -147,6 +148,7 @@ int main(int argc, char** argv)
QStringList args = QApplication::arguments();
std::string binaryDirectory;
std::string sourceDirectory;
+ std::string presetName;
for (int i = 1; i < args.size(); ++i) {
const QString& arg = args[i];
if (arg.startsWith("-S")) {
@@ -185,11 +187,28 @@ int main(int argc, char** argv)
binaryDirectory =
cmSystemTools::CollapseFullPath(path.toLocal8Bit().data());
cmSystemTools::ConvertToUnixSlashes(binaryDirectory);
+ } else if (arg.startsWith("--preset=")) {
+ QString preset = arg.mid(cmStrLen("--preset="));
+ if (preset.isEmpty()) {
+ std::cerr << "No preset specified for --preset" << std::endl;
+ return 1;
+ }
+ presetName = preset.toLocal8Bit().data();
}
}
- if (!sourceDirectory.empty() && !binaryDirectory.empty()) {
+ if (!sourceDirectory.empty() &&
+ (!binaryDirectory.empty() || !presetName.empty())) {
dialog.setSourceDirectory(QString::fromLocal8Bit(sourceDirectory.c_str()));
- dialog.setBinaryDirectory(QString::fromLocal8Bit(binaryDirectory.c_str()));
+ if (!binaryDirectory.empty()) {
+ dialog.setBinaryDirectory(
+ QString::fromLocal8Bit(binaryDirectory.c_str()));
+ if (!presetName.empty()) {
+ dialog.setStartupBinaryDirectory(true);
+ }
+ }
+ if (!presetName.empty()) {
+ dialog.setDeferredPreset(QString::fromLocal8Bit(presetName.c_str()));
+ }
} else {
if (args.count() == 2) {
std::string filePath =
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index df22028..acd32ec 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -21,8 +21,10 @@
#include <QSettings>
#include <QShortcut>
#include <QStatusBar>
+#include <QString>
#include <QToolButton>
#include <QUrl>
+#include <QVector>
#ifdef QT_WINEXTRAS
# include <QWinTaskbarButton>
@@ -263,6 +265,8 @@ void CMakeSetupDialog::initialize()
&CMakeSetupDialog::onBinaryDirectoryChanged);
QObject::connect(this->SourceDirectory, &QLineEdit::textChanged, this,
&CMakeSetupDialog::onSourceDirectoryChanged);
+ QObject::connect(this->Preset, &QCMakePresetComboBox::presetChanged, this,
+ &CMakeSetupDialog::onBuildPresetChanged);
QObject::connect(this->CMakeThread->cmakeInstance(),
&QCMake::sourceDirChanged, this,
@@ -270,6 +274,13 @@ void CMakeSetupDialog::initialize()
QObject::connect(this->CMakeThread->cmakeInstance(),
&QCMake::binaryDirChanged, this,
&CMakeSetupDialog::updateBinaryDirectory);
+ QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::presetsChanged,
+ this, &CMakeSetupDialog::updatePresets);
+ QObject::connect(this->CMakeThread->cmakeInstance(), &QCMake::presetChanged,
+ this, &CMakeSetupDialog::updatePreset);
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ &QCMake::presetLoadError, this,
+ &CMakeSetupDialog::showPresetLoadError);
QObject::connect(this->CMakeThread->cmakeInstance(),
&QCMake::progressChanged, this,
@@ -314,9 +325,15 @@ void CMakeSetupDialog::initialize()
QObject::connect(this->WarnUninitializedAction, &QAction::triggered,
this->CMakeThread->cmakeInstance(),
&QCMake::setWarnUninitializedMode);
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ &QCMake::warnUninitializedModeChanged,
+ this->WarnUninitializedAction, &QAction::setChecked);
- if (!this->SourceDirectory->text().isEmpty() ||
- !this->BinaryDirectory->lineEdit()->text().isEmpty()) {
+ if (!this->SourceDirectory->text().isEmpty() &&
+ !this->DeferredPreset.isNull()) {
+ this->onSourceDirectoryChanged(this->SourceDirectory->text());
+ } else if (!this->SourceDirectory->text().isEmpty() ||
+ !this->BinaryDirectory->lineEdit()->text().isEmpty()) {
this->onSourceDirectoryChanged(this->SourceDirectory->text());
this->onBinaryDirectoryChanged(this->BinaryDirectory->lineEdit()->text());
} else {
@@ -671,6 +688,41 @@ void CMakeSetupDialog::updateBinaryDirectory(const QString& dir)
}
}
+void CMakeSetupDialog::updatePresets(const QVector<QCMakePreset>& presets)
+{
+ if (this->Preset->presets() != presets) {
+ this->Preset->blockSignals(true);
+ this->Preset->setPresets(presets);
+ this->Preset->blockSignals(false);
+ }
+
+ this->Preset->setHidden(presets.isEmpty());
+ this->PresetLabel->setHidden(presets.isEmpty());
+
+ if (!this->DeferredPreset.isNull()) {
+ this->Preset->setPresetName(this->DeferredPreset);
+ this->DeferredPreset = QString{};
+ }
+}
+
+void CMakeSetupDialog::updatePreset(const QString& name)
+{
+ if (this->Preset->presetName() != name) {
+ this->Preset->blockSignals(true);
+ this->Preset->setPresetName(name);
+ this->Preset->blockSignals(false);
+ }
+}
+
+void CMakeSetupDialog::showPresetLoadError(
+ const QString& dir, cmCMakePresetsFile::ReadFileResult result)
+{
+ QMessageBox::warning(
+ this, "Error Reading CMake Presets",
+ QString::fromLocal8Bit("Could not read presets from %1: %2")
+ .arg(dir, cmCMakePresetsFile::ResultToString(result)));
+}
+
void CMakeSetupDialog::doBinaryBrowse()
{
QString dir = QFileDialog::getExistingDirectory(
@@ -686,6 +738,11 @@ void CMakeSetupDialog::setBinaryDirectory(const QString& dir)
this->BinaryDirectory->setEditText(dir);
}
+void CMakeSetupDialog::setStartupBinaryDirectory(bool startup)
+{
+ this->StartupBinaryDirectory = startup;
+}
+
void CMakeSetupDialog::onSourceDirectoryChanged(const QString& dir)
{
this->Output->clear();
@@ -711,11 +768,24 @@ void CMakeSetupDialog::onBinaryDirectoryChanged(const QString& dir)
Q_ARG(QString, dir));
}
+void CMakeSetupDialog::onBuildPresetChanged(const QString& name)
+{
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "setPreset",
+ Qt::QueuedConnection, Q_ARG(QString, name),
+ Q_ARG(bool, !this->StartupBinaryDirectory));
+ this->StartupBinaryDirectory = false;
+}
+
void CMakeSetupDialog::setSourceDirectory(const QString& dir)
{
this->SourceDirectory->setText(dir);
}
+void CMakeSetupDialog::setDeferredPreset(const QString& preset)
+{
+ this->DeferredPreset = preset;
+}
+
void CMakeSetupDialog::showProgress(const QString& /*msg*/, float percent)
{
percent = (percent * ProgressFactor) + ProgressOffset;
@@ -753,6 +823,7 @@ void CMakeSetupDialog::setEnabledState(bool enabled)
this->CacheValues->cacheModel()->setEditEnabled(enabled);
this->SourceDirectory->setEnabled(enabled);
this->BrowseSourceDirectoryButton->setEnabled(enabled);
+ this->Preset->setEnabled(enabled);
this->BinaryDirectory->setEnabled(enabled);
this->BrowseBinaryDirectoryButton->setEnabled(enabled);
this->ReloadCacheAction->setEnabled(enabled);
@@ -777,6 +848,17 @@ bool CMakeSetupDialog::setupFirstConfigure()
// restore from settings
dialog.loadFromSettings();
+ auto presetData = this->Preset->currentData();
+ if (presetData.isValid()) {
+ auto preset = presetData.value<QCMakePreset>();
+ dialog.setCurrentGenerator(preset.generator);
+ if (preset.setGenConfig) {
+ dialog.setPlatform(preset.architecture);
+ dialog.setToolset(preset.toolset);
+ }
+ dialog.setCompilerOption(CompilerOption::DefaultNative);
+ }
+
if (dialog.exec() == QDialog::Accepted) {
dialog.saveToSettings();
this->CMakeThread->cmakeInstance()->setGenerator(dialog.getGenerator());
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index d752ef2..f0cc929 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -5,12 +5,15 @@
#include <memory>
#include "QCMake.h"
+#include "QCMakePreset.h"
#include <QEventLoop>
#include <QMainWindow>
#include <QThread>
+#include <QVector>
#include "ui_CMakeSetupDialog.h"
+class QCMakePresetItemModel;
class QCMakeThread;
class CMakeCacheModel;
class QProgressBar;
@@ -33,6 +36,8 @@ public:
public slots:
void setBinaryDirectory(const QString& dir);
void setSourceDirectory(const QString& dir);
+ void setDeferredPreset(const QString& preset);
+ void setStartupBinaryDirectory(bool startup);
protected slots:
void initialize();
@@ -52,6 +57,10 @@ protected slots:
void doDeleteCache();
void updateSourceDirectory(const QString& dir);
void updateBinaryDirectory(const QString& dir);
+ void updatePresets(const QVector<QCMakePreset>& presets);
+ void updatePreset(const QString& name);
+ void showPresetLoadError(const QString& dir,
+ cmCMakePresetsFile::ReadFileResult result);
void showProgress(const QString& msg, float percent);
void setEnabledState(bool);
bool setupFirstConfigure();
@@ -62,6 +71,7 @@ protected slots:
void saveBuildPaths(const QStringList&);
void onBinaryDirectoryChanged(const QString& dir);
void onSourceDirectoryChanged(const QString& dir);
+ void onBuildPresetChanged(const QString& name);
void setCacheModified();
void removeSelectedCacheEntries();
void selectionChanged();
@@ -113,6 +123,8 @@ protected:
QAction* WarnUninitializedAction;
QAction* InstallForCommandLineAction;
State CurrentState;
+ QString DeferredPreset;
+ bool StartupBinaryDirectory = false;
QTextCharFormat ErrorFormat;
QTextCharFormat MessageFormat;
diff --git a/Source/QtDialog/CMakeSetupDialog.ui b/Source/QtDialog/CMakeSetupDialog.ui
index 5feee91..afb25eb 100644
--- a/Source/QtDialog/CMakeSetupDialog.ui
+++ b/Source/QtDialog/CMakeSetupDialog.ui
@@ -44,7 +44,7 @@
<number>6</number>
</property>
<item row="0" column="0">
- <widget class="QLabel" name="label">
+ <widget class="QLabel" name="SourceLabel">
<property name="text">
<string>Where is the source code:</string>
</property>
@@ -61,13 +61,23 @@
</widget>
</item>
<item row="1" column="0">
- <widget class="QLabel" name="label_2">
+ <widget class="QLabel" name="PresetLabel">
<property name="text">
- <string>Where to build the binaries:</string>
+ <string>Preset:</string>
</property>
</widget>
</item>
<item row="1" column="1">
+ <widget class="QCMakePresetComboBox" name="Preset"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="BinaryLabel">
+ <property name="text">
+ <string>Where to build the binaries:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
<widget class="QComboBox" name="BinaryDirectory">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Fixed">
@@ -83,7 +93,7 @@
</property>
</widget>
</item>
- <item row="1" column="2">
+ <item row="2" column="2">
<widget class="QPushButton" name="BrowseBinaryDirectoryButton">
<property name="text">
<string>Browse &amp;Build...</string>
@@ -367,6 +377,11 @@
<extends>QTreeView</extends>
<header>QCMakeCacheView.h</header>
</customwidget>
+ <customwidget>
+ <class>QCMakePresetComboBox</class>
+ <extends>QComboBox</extends>
+ <header>QCMakePresetComboBox.h</header>
+ </customwidget>
</customwidgets>
<resources>
<include location="CMakeSetup.qrc"/>
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
index 918f137..10360bb 100644
--- a/Source/QtDialog/FirstConfigure.cxx
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -145,6 +145,36 @@ void StartCompilerSetup::setCurrentGenerator(const QString& gen)
}
}
+void StartCompilerSetup::setPlatform(const QString& platform)
+{
+ this->PlatformOptions->setCurrentText(platform);
+}
+
+void StartCompilerSetup::setToolset(const QString& toolset)
+{
+ this->Toolset->setText(toolset);
+}
+
+void StartCompilerSetup::setCompilerOption(CompilerOption option)
+{
+ std::size_t index = 0;
+ switch (option) {
+ case CompilerOption::DefaultNative:
+ index = 0;
+ break;
+ case CompilerOption::SpecifyNative:
+ index = 1;
+ break;
+ case CompilerOption::ToolchainFile:
+ index = 2;
+ break;
+ case CompilerOption::Options:
+ index = 3;
+ break;
+ }
+ this->CompilerSetupOptions[index]->setChecked(true);
+}
+
QString StartCompilerSetup::getGenerator() const
{
return this->GeneratorOptions->currentText();
@@ -482,6 +512,26 @@ void FirstConfigure::setGenerators(
this->mStartCompilerSetupPage->setGenerators(gens);
}
+void FirstConfigure::setCurrentGenerator(const QString& gen)
+{
+ this->mStartCompilerSetupPage->setCurrentGenerator(gen);
+}
+
+void FirstConfigure::setPlatform(const QString& platform)
+{
+ this->mStartCompilerSetupPage->setPlatform(platform);
+}
+
+void FirstConfigure::setToolset(const QString& toolset)
+{
+ this->mStartCompilerSetupPage->setToolset(toolset);
+}
+
+void FirstConfigure::setCompilerOption(CompilerOption option)
+{
+ this->mStartCompilerSetupPage->setCompilerOption(option);
+}
+
QString FirstConfigure::getGenerator() const
{
return this->mStartCompilerSetupPage->getGenerator();
@@ -503,7 +553,7 @@ void FirstConfigure::loadFromSettings()
// restore generator
settings.beginGroup("Settings/StartPath");
QString lastGen = settings.value("LastGenerator").toString();
- this->mStartCompilerSetupPage->setCurrentGenerator(lastGen);
+ this->setCurrentGenerator(lastGen);
settings.endGroup();
// restore compiler setup
@@ -550,7 +600,7 @@ void FirstConfigure::loadFromSettings()
// this prevents them from being taken from environment, while the
// generator is taken from application settings
if (!mDefaultGenerator.isEmpty()) {
- this->mStartCompilerSetupPage->setCurrentGenerator(mDefaultGenerator);
+ this->setCurrentGenerator(mDefaultGenerator);
}
}
diff --git a/Source/QtDialog/FirstConfigure.h b/Source/QtDialog/FirstConfigure.h
index ca5f52e..5844f3a 100644
--- a/Source/QtDialog/FirstConfigure.h
+++ b/Source/QtDialog/FirstConfigure.h
@@ -22,6 +22,14 @@ enum FirstConfigurePages
Done
};
+enum class CompilerOption
+{
+ DefaultNative,
+ SpecifyNative,
+ ToolchainFile,
+ Options,
+};
+
//! the first page that gives basic options for what compilers setup to choose
//! from
class StartCompilerSetup : public QWizardPage
@@ -33,6 +41,9 @@ public:
~StartCompilerSetup();
void setGenerators(std::vector<cmake::GeneratorInfo> const& gens);
void setCurrentGenerator(const QString& gen);
+ void setToolset(const QString& toolset);
+ void setPlatform(const QString& platform);
+ void setCompilerOption(CompilerOption option);
QString getGenerator() const;
QString getToolset() const;
QString getPlatform() const;
@@ -167,6 +178,10 @@ public:
~FirstConfigure();
void setGenerators(std::vector<cmake::GeneratorInfo> const& gens);
+ void setCurrentGenerator(const QString& gen);
+ void setToolset(const QString& toolset);
+ void setPlatform(const QString& platform);
+ void setCompilerOption(CompilerOption option);
QString getGenerator() const;
QString getPlatform() const;
QString getToolset() const;
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index 974c545..9017a63 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -2,10 +2,14 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "QCMake.h"
+#include <algorithm>
+
#include <cm/memory>
#include <QCoreApplication>
#include <QDir>
+#include <QString>
+#include <QVector>
#include "cmExternalMakefileProjectGenerator.h"
#include "cmGlobalGenerator.h"
@@ -19,12 +23,15 @@
QCMake::QCMake(QObject* p)
: QObject(p)
+ , StartEnvironment(QProcessEnvironment::systemEnvironment())
, Environment(QProcessEnvironment::systemEnvironment())
{
this->WarnUninitializedMode = false;
qRegisterMetaType<QCMakeProperty>();
qRegisterMetaType<QCMakePropertyList>();
qRegisterMetaType<QProcessEnvironment>();
+ qRegisterMetaType<QVector<QCMakePreset>>();
+ qRegisterMetaType<cmCMakePresetsFile::ReadFileResult>();
cmSystemTools::DisableRunCommandOutput();
cmSystemTools::SetRunCommandHideConsole(true);
@@ -57,6 +64,17 @@ QCMake::QCMake(QObject* p)
for (cmake::GeneratorInfo const& gen : generators) {
this->AvailableGenerators.push_back(gen);
}
+
+ connect(&this->LoadPresetsTimer, &QTimer::timeout, this, [this]() {
+ this->loadPresets();
+ if (!this->PresetName.isEmpty() &&
+ this->CMakePresetsFile.Presets.find(
+ std::string(this->PresetName.toLocal8Bit())) ==
+ this->CMakePresetsFile.Presets.end()) {
+ this->setPreset(QString{});
+ }
+ });
+ this->LoadPresetsTimer.start(1000);
}
QCMake::~QCMake() = default;
@@ -73,6 +91,8 @@ void QCMake::setSourceDirectory(const QString& _dir)
if (this->SourceDirectory != dir) {
this->SourceDirectory = QDir::fromNativeSeparators(dir);
emit this->sourceDirChanged(this->SourceDirectory);
+ this->loadPresets();
+ this->setPreset(QString{});
}
}
@@ -129,6 +149,56 @@ void QCMake::setBinaryDirectory(const QString& _dir)
}
}
+void QCMake::setPreset(const QString& name, bool setBinary)
+{
+ if (this->PresetName != name) {
+ this->PresetName = name;
+ emit this->presetChanged(this->PresetName);
+
+ if (!name.isNull()) {
+ std::string presetName(name.toLocal8Bit());
+ auto const& preset = this->CMakePresetsFile.Presets[presetName];
+ auto expandedPreset = this->CMakePresetsFile.ExpandMacros(preset);
+ if (expandedPreset) {
+ if (setBinary) {
+ QString binaryDir =
+ QString::fromLocal8Bit(expandedPreset->BinaryDir.data());
+ this->setBinaryDirectory(binaryDir);
+ }
+ if (expandedPreset->WarnDev) {
+ this->CMakeInstance->SetSuppressDevWarnings(
+ !*expandedPreset->WarnDev);
+ }
+ if (expandedPreset->ErrorDev) {
+ this->CMakeInstance->SetDevWarningsAsErrors(
+ *expandedPreset->ErrorDev);
+ }
+ if (expandedPreset->WarnDeprecated) {
+ this->CMakeInstance->SetSuppressDeprecatedWarnings(
+ !*expandedPreset->WarnDeprecated);
+ }
+ if (expandedPreset->ErrorDeprecated) {
+ this->CMakeInstance->SetDeprecatedWarningsAsErrors(
+ *expandedPreset->ErrorDeprecated);
+ }
+ if (expandedPreset->WarnUninitialized) {
+ this->WarnUninitializedMode = *expandedPreset->WarnUninitialized;
+ emit this->warnUninitializedModeChanged(
+ *expandedPreset->WarnUninitialized);
+ }
+ this->Environment = this->StartEnvironment;
+ for (auto const& v : expandedPreset->Environment) {
+ if (v.second) {
+ this->Environment.insert(QString::fromLocal8Bit(v.first.data()),
+ QString::fromLocal8Bit(v.second->data()));
+ }
+ }
+ }
+ }
+ emit this->propertiesChanged(this->properties());
+ }
+}
+
void QCMake::setGenerator(const QString& gen)
{
if (this->Generator != gen) {
@@ -348,6 +418,56 @@ QCMakePropertyList QCMake::properties() const
ret.append(prop);
}
+ if (!this->PresetName.isNull()) {
+ std::string presetName(this->PresetName.toLocal8Bit());
+ auto p = this->CMakePresetsFile.ExpandMacros(
+ this->CMakePresetsFile.Presets.at(presetName));
+ if (p) {
+ for (auto const& v : p->CacheVariables) {
+ if (!v.second) {
+ continue;
+ }
+ QCMakeProperty prop;
+ prop.Key = QString::fromLocal8Bit(v.first.data());
+ prop.Value = QString::fromLocal8Bit(v.second->Value.data());
+ prop.Type = QCMakeProperty::STRING;
+ if (!v.second->Type.empty()) {
+ auto type = cmState::StringToCacheEntryType(v.second->Type);
+ switch (type) {
+ case cmStateEnums::BOOL:
+ prop.Type = QCMakeProperty::BOOL;
+ prop.Value = cmIsOn(v.second->Value);
+ break;
+ case cmStateEnums::PATH:
+ prop.Type = QCMakeProperty::PATH;
+ break;
+ case cmStateEnums::FILEPATH:
+ prop.Type = QCMakeProperty::FILEPATH;
+ break;
+ default:
+ prop.Type = QCMakeProperty::STRING;
+ break;
+ }
+ }
+
+ // QCMakeCacheModel prefers variables earlier in the list rather than
+ // later, so overwrite them if they already exist rather than simply
+ // appending
+ bool found = false;
+ for (auto& orig : ret) {
+ if (orig.Key == prop.Key) {
+ orig = prop;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ret.append(prop);
+ }
+ }
+ }
+ }
+
return ret;
}
@@ -405,6 +525,46 @@ void QCMake::setUpEnvironment() const
}
}
+void QCMake::loadPresets()
+{
+ auto result = this->CMakePresetsFile.ReadProjectPresets(
+ this->SourceDirectory.toLocal8Bit().data(), true);
+ if (result != this->LastLoadPresetsResult &&
+ result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
+ emit this->presetLoadError(this->SourceDirectory, result);
+ }
+ this->LastLoadPresetsResult = result;
+
+ QVector<QCMakePreset> presets;
+ for (auto const& name : this->CMakePresetsFile.PresetOrder) {
+ auto const& p = this->CMakePresetsFile.Presets[name];
+ if (p.Hidden) {
+ continue;
+ }
+
+ QCMakePreset preset;
+ preset.name = std::move(QString::fromLocal8Bit(p.Name.data()));
+ preset.displayName =
+ std::move(QString::fromLocal8Bit(p.DisplayName.data()));
+ preset.description =
+ std::move(QString::fromLocal8Bit(p.Description.data()));
+ preset.generator = std::move(QString::fromLocal8Bit(p.Generator.data()));
+ preset.architecture =
+ std::move(QString::fromLocal8Bit(p.Architecture.data()));
+ preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data()));
+ preset.setGenConfig = !p.GeneratorConfig ||
+ p.GeneratorConfig == cmCMakePresetsFile::CMakeGeneratorConfig::Default;
+ preset.enabled = std::find_if(this->AvailableGenerators.begin(),
+ this->AvailableGenerators.end(),
+ [&p](const cmake::GeneratorInfo& g) {
+ return g.name == p.Generator;
+ }) != this->AvailableGenerators.end() &&
+ this->CMakePresetsFile.ExpandMacros(p);
+ presets.push_back(preset);
+ }
+ emit this->presetsChanged(presets);
+}
+
QString QCMake::binaryDirectory() const
{
return this->BinaryDirectory;
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index f569951..a6751b0 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmCMakePresetsFile.h"
#include "cmake.h"
#ifdef _MSC_VER
@@ -14,6 +15,7 @@
#include <memory>
#include <vector>
+#include "QCMakePreset.h"
#include <QAtomicInt>
#include <QList>
#include <QMetaType>
@@ -21,6 +23,7 @@
#include <QProcessEnvironment>
#include <QString>
#include <QStringList>
+#include <QTimer>
#include <QVariant>
/// struct to represent cmake properties in Qt
@@ -57,6 +60,7 @@ using QCMakePropertyList = QList<QCMakeProperty>;
Q_DECLARE_METATYPE(QCMakeProperty)
Q_DECLARE_METATYPE(QCMakePropertyList)
Q_DECLARE_METATYPE(QProcessEnvironment)
+Q_DECLARE_METATYPE(cmCMakePresetsFile::ReadFileResult)
/// Qt API for CMake library.
/// Wrapper like class allows for easier integration with
@@ -74,6 +78,8 @@ public slots:
void setSourceDirectory(const QString& dir);
/// set the binary directory to build in
void setBinaryDirectory(const QString& dir);
+ /// set the preset name to use
+ void setPreset(const QString& name, bool setBinary = true);
/// set the desired generator to use
void setGenerator(const QString& generator);
/// set the desired generator to use
@@ -147,6 +153,15 @@ signals:
void sourceDirChanged(const QString& dir);
/// signal when the binary directory changes
void binaryDirChanged(const QString& dir);
+ /// signal when the preset list changes
+ void presetsChanged(const QVector<QCMakePreset>& presets);
+ /// signal when the selected preset changes
+ void presetChanged(const QString& name);
+ /// signal when there's an error reading the presets files
+ void presetLoadError(const QString& dir,
+ cmCMakePresetsFile::ReadFileResult error);
+ /// signal when uninitialized warning changes
+ void warnUninitializedModeChanged(bool value);
/// signal for progress events
void progressChanged(const QString& msg, float percent);
/// signal when configure is done
@@ -178,6 +193,8 @@ protected:
void stderrCallback(std::string const& msg);
void setUpEnvironment() const;
+ void loadPresets();
+
bool WarnUninitializedMode;
QString SourceDirectory;
QString BinaryDirectory;
@@ -185,7 +202,13 @@ protected:
QString Platform;
QString Toolset;
std::vector<cmake::GeneratorInfo> AvailableGenerators;
+ cmCMakePresetsFile CMakePresetsFile;
+ cmCMakePresetsFile::ReadFileResult LastLoadPresetsResult =
+ cmCMakePresetsFile::ReadFileResult::READ_OK;
+ QString PresetName;
QString CMakeExecutable;
QAtomicInt InterruptFlag;
+ QProcessEnvironment StartEnvironment;
QProcessEnvironment Environment;
+ QTimer LoadPresetsTimer;
};
diff --git a/Source/QtDialog/QCMakePreset.cxx b/Source/QtDialog/QCMakePreset.cxx
new file mode 100644
index 0000000..b10cf07
--- /dev/null
+++ b/Source/QtDialog/QCMakePreset.cxx
@@ -0,0 +1,50 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMakePreset.h"
+
+bool operator==(const QCMakePreset& lhs, const QCMakePreset& rhs)
+{
+ return lhs.name == rhs.name && lhs.displayName == rhs.displayName &&
+ lhs.description == rhs.description && lhs.generator == rhs.generator &&
+ lhs.architecture == rhs.architecture && lhs.toolset == rhs.toolset &&
+ lhs.setGenConfig == rhs.setGenConfig && lhs.enabled == rhs.enabled;
+}
+
+bool operator!=(const QCMakePreset& lhs, const QCMakePreset& rhs)
+{
+ return !(lhs == rhs);
+}
+
+bool operator<(const QCMakePreset& lhs, const QCMakePreset& rhs)
+{
+ return lhs.name < rhs.name ||
+ (lhs.name == rhs.name &&
+ (lhs.displayName < rhs.displayName ||
+ (lhs.displayName == rhs.displayName &&
+ (lhs.description < rhs.description ||
+ (lhs.description == rhs.description &&
+ (lhs.generator < rhs.generator ||
+ (lhs.generator == rhs.generator &&
+ (lhs.architecture < rhs.architecture ||
+ (lhs.architecture == rhs.architecture &&
+ (lhs.toolset < rhs.toolset ||
+ (lhs.toolset == rhs.toolset &&
+ (lhs.setGenConfig < rhs.setGenConfig ||
+ (lhs.setGenConfig == rhs.setGenConfig &&
+ (lhs.enabled < rhs.enabled))))))))))))));
+}
+
+bool operator<=(const QCMakePreset& lhs, const QCMakePreset& rhs)
+{
+ return rhs >= lhs;
+}
+
+bool operator>(const QCMakePreset& lhs, const QCMakePreset& rhs)
+{
+ return rhs < lhs;
+}
+
+bool operator>=(const QCMakePreset& lhs, const QCMakePreset& rhs)
+{
+ return !(lhs < rhs);
+}
diff --git a/Source/QtDialog/QCMakePreset.h b/Source/QtDialog/QCMakePreset.h
new file mode 100644
index 0000000..93d70d8
--- /dev/null
+++ b/Source/QtDialog/QCMakePreset.h
@@ -0,0 +1,30 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <QString>
+#include <QVariant>
+
+#include "cmCMakePresetsFile.h"
+
+class QCMakePreset
+{
+public:
+ QString name;
+ QString displayName;
+ QString description;
+ QString generator;
+ QString architecture;
+ QString toolset;
+ bool setGenConfig;
+ bool enabled;
+};
+
+bool operator==(const QCMakePreset& lhs, const QCMakePreset& rhs);
+bool operator!=(const QCMakePreset& lhs, const QCMakePreset& rhs);
+bool operator<(const QCMakePreset& lhs, const QCMakePreset& rhs);
+bool operator<=(const QCMakePreset& lhs, const QCMakePreset& rhs);
+bool operator>(const QCMakePreset& lhs, const QCMakePreset& rhs);
+bool operator>=(const QCMakePreset& lhs, const QCMakePreset& rhs);
+
+Q_DECLARE_METATYPE(QCMakePreset)
diff --git a/Source/QtDialog/QCMakePresetComboBox.cxx b/Source/QtDialog/QCMakePresetComboBox.cxx
new file mode 100644
index 0000000..efadb73
--- /dev/null
+++ b/Source/QtDialog/QCMakePresetComboBox.cxx
@@ -0,0 +1,64 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMakePresetComboBox.h"
+
+#include "QCMakePresetItemModel.h"
+
+QCMakePresetComboBox::QCMakePresetComboBox(QWidget* parent)
+ : QComboBox(parent)
+{
+ this->m_model = new QCMakePresetItemModel(this);
+ this->setModel(this->m_model);
+
+ QObject::connect(this->m_model, &QCMakePresetItemModel::modelAboutToBeReset,
+ this, [this]() { this->m_resetting = true; });
+ QObject::connect(this->m_model, &QCMakePresetItemModel::modelReset, this,
+ [this]() {
+ this->setPresetName(this->m_lastPreset);
+ this->m_resetting = false;
+ this->emitPresetChanged();
+ });
+ QObject::connect(
+ this,
+ static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ this, [this](int /*row*/) {
+ if (!this->m_resetting) {
+ this->emitPresetChanged();
+ }
+ });
+}
+
+const QVector<QCMakePreset>& QCMakePresetComboBox::presets() const
+{
+ return this->m_model->presets();
+}
+
+QString QCMakePresetComboBox::presetName() const
+{
+ auto preset = this->currentData();
+ if (preset.canConvert<QCMakePreset>()) {
+ return preset.value<QCMakePreset>().name;
+ }
+ return QString{};
+}
+
+void QCMakePresetComboBox::setPresets(const QVector<QCMakePreset>& presets)
+{
+ this->m_model->setPresets(presets);
+}
+
+void QCMakePresetComboBox::setPresetName(const QString& name)
+{
+ this->setCurrentIndex(this->m_model->presetNameToRow(name));
+ if (this->signalsBlocked()) {
+ this->m_lastPreset = this->presetName();
+ }
+}
+
+void QCMakePresetComboBox::emitPresetChanged()
+{
+ if (this->presetName() != this->m_lastPreset) {
+ emit this->presetChanged(this->presetName());
+ this->m_lastPreset = this->presetName();
+ }
+}
diff --git a/Source/QtDialog/QCMakePresetComboBox.h b/Source/QtDialog/QCMakePresetComboBox.h
new file mode 100644
index 0000000..d1eeffe
--- /dev/null
+++ b/Source/QtDialog/QCMakePresetComboBox.h
@@ -0,0 +1,35 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "QCMakePreset.h"
+#include <QComboBox>
+#include <QObject>
+#include <QString>
+#include <QVector>
+
+class QCMakePresetItemModel;
+
+class QCMakePresetComboBox : public QComboBox
+{
+ Q_OBJECT
+public:
+ QCMakePresetComboBox(QWidget* parent = nullptr);
+
+ const QVector<QCMakePreset>& presets() const;
+ QString presetName() const;
+
+public slots:
+ void setPresets(const QVector<QCMakePreset>& presets);
+ void setPresetName(const QString& name);
+
+signals:
+ void presetChanged(const QString& name);
+
+private:
+ QCMakePresetItemModel* m_model;
+ bool m_resetting = false;
+ QString m_lastPreset;
+
+ void emitPresetChanged();
+};
diff --git a/Source/QtDialog/QCMakePresetItemModel.cxx b/Source/QtDialog/QCMakePresetItemModel.cxx
new file mode 100644
index 0000000..00a4e18
--- /dev/null
+++ b/Source/QtDialog/QCMakePresetItemModel.cxx
@@ -0,0 +1,143 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMakePresetItemModel.h"
+
+#include <QFont>
+
+QCMakePresetItemModel::QCMakePresetItemModel(QObject* parent)
+ : QAbstractItemModel(parent)
+{
+}
+
+QVariant QCMakePresetItemModel::data(const QModelIndex& index, int role) const
+{
+ switch (role) {
+ case Qt::AccessibleDescriptionRole:
+ // Separators have to return "separator" for the
+ // AccessibleDescriptionRole. This was determined by looking at
+ // QComboBoxDelegate::isSeparator() (located in qcombobox_p.h.)
+ if (index.internalId() == SEPARATOR_INDEX) {
+ return QString::fromLocal8Bit("separator");
+ }
+ return QString{};
+ case Qt::DisplayRole: {
+ if (index.internalId() == CUSTOM_INDEX) {
+ return QString::fromLocal8Bit("<custom>");
+ }
+ if (index.internalId() == SEPARATOR_INDEX) {
+ return QVariant{};
+ }
+ auto const& preset = this->m_presets[index.internalId()];
+ return preset.displayName.isEmpty() ? preset.name : preset.displayName;
+ }
+ case Qt::ToolTipRole:
+ if (index.internalId() == CUSTOM_INDEX) {
+ return QString::fromLocal8Bit("Specify all settings manually");
+ }
+ if (index.internalId() == SEPARATOR_INDEX) {
+ return QVariant{};
+ }
+ return this->m_presets[index.internalId()].description;
+ case Qt::UserRole:
+ if (index.internalId() == CUSTOM_INDEX) {
+ return QVariant{};
+ }
+ if (index.internalId() == SEPARATOR_INDEX) {
+ return QVariant{};
+ }
+ return QVariant::fromValue(this->m_presets[index.internalId()]);
+ case Qt::FontRole:
+ if (index.internalId() == CUSTOM_INDEX) {
+ QFont font;
+ font.setItalic(true);
+ return font;
+ }
+ return QFont{};
+ default:
+ return QVariant{};
+ }
+}
+
+Qt::ItemFlags QCMakePresetItemModel::flags(const QModelIndex& index) const
+{
+ Qt::ItemFlags flags =
+ Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
+ if (index.internalId() != SEPARATOR_INDEX &&
+ (index.internalId() == CUSTOM_INDEX ||
+ this->m_presets[index.internalId()].enabled)) {
+ flags |= Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+ }
+ return flags;
+}
+
+int QCMakePresetItemModel::rowCount(const QModelIndex& parent) const
+{
+ if (parent.isValid()) {
+ return 0;
+ }
+ if (this->m_presets.empty()) {
+ return 1;
+ }
+ return this->m_presets.size() + 2;
+}
+
+int QCMakePresetItemModel::columnCount(const QModelIndex& parent) const
+{
+ if (parent.isValid()) {
+ return 0;
+ }
+ return 1;
+}
+
+QModelIndex QCMakePresetItemModel::index(int row, int column,
+ const QModelIndex& parent) const
+{
+ if (parent.isValid() || column != 0 || row < 0 ||
+ row >= this->rowCount(QModelIndex{})) {
+ return QModelIndex{};
+ }
+
+ if (this->m_presets.empty() || row == this->m_presets.size() + 1) {
+ return this->createIndex(row, column, CUSTOM_INDEX);
+ }
+
+ if (row == this->m_presets.size()) {
+ return this->createIndex(row, column, SEPARATOR_INDEX);
+ }
+
+ return this->createIndex(row, column, static_cast<quintptr>(row));
+}
+
+QModelIndex QCMakePresetItemModel::parent(const QModelIndex& /*index*/) const
+{
+ return QModelIndex{};
+}
+
+QVector<QCMakePreset> const& QCMakePresetItemModel::presets() const
+{
+ return this->m_presets;
+}
+
+void QCMakePresetItemModel::setPresets(QVector<QCMakePreset> const& presets)
+{
+ this->beginResetModel();
+ this->m_presets = presets;
+ this->endResetModel();
+}
+
+int QCMakePresetItemModel::presetNameToRow(const QString& name) const
+{
+ if (this->m_presets.empty()) {
+ return 0;
+ }
+
+ int index = 0;
+ for (auto const& preset : this->m_presets) {
+ if (preset.name == name) {
+ return index;
+ }
+ index++;
+ }
+
+ return this->m_presets.size() + 1;
+}
diff --git a/Source/QtDialog/QCMakePresetItemModel.h b/Source/QtDialog/QCMakePresetItemModel.h
new file mode 100644
index 0000000..79fba29
--- /dev/null
+++ b/Source/QtDialog/QCMakePresetItemModel.h
@@ -0,0 +1,45 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <cm/optional>
+
+#include "QCMakePreset.h"
+#include <QAbstractItemModel>
+#include <QModelIndex>
+#include <QString>
+#include <QVariant>
+#include <QVector>
+#include <QtGlobal>
+
+class QObject;
+
+class QCMakePresetItemModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ QCMakePresetItemModel(QObject* parent = nullptr);
+
+ QVariant data(const QModelIndex& index, int role) const override;
+ Qt::ItemFlags flags(const QModelIndex& index) const override;
+
+ int rowCount(const QModelIndex& parent = QModelIndex{}) const override;
+ int columnCount(const QModelIndex& parent = QModelIndex{}) const override;
+
+ QModelIndex index(int row, int column,
+ const QModelIndex& parent = QModelIndex{}) const override;
+ QModelIndex parent(const QModelIndex& index) const override;
+
+ QVector<QCMakePreset> const& presets() const;
+
+ int presetNameToRow(const QString& name) const;
+
+public slots:
+ void setPresets(QVector<QCMakePreset> const& presets);
+
+private:
+ QVector<QCMakePreset> m_presets;
+
+ static constexpr quintptr SEPARATOR_INDEX = static_cast<quintptr>(-2);
+ static constexpr quintptr CUSTOM_INDEX = static_cast<quintptr>(-1);
+};
diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx
new file mode 100644
index 0000000..25997fd
--- /dev/null
+++ b/Source/cmCMakePresetsFile.cxx
@@ -0,0 +1,763 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCMakePresetsFile.h"
+
+#include <cstdlib>
+#include <functional>
+#include <utility>
+
+#include <cmext/string_view>
+
+#include <cm3p/json/reader.h>
+#include <cm3p/json/value.h>
+
+#include "cmsys/FStream.hxx"
+
+#include "cmJSONHelpers.h"
+#include "cmStringAlgorithms.h"
+#include "cmSystemTools.h"
+#include "cmVersion.h"
+
+namespace {
+enum class CycleStatus
+{
+ Unvisited,
+ InProgress,
+ Verified,
+};
+
+using ReadFileResult = cmCMakePresetsFile::ReadFileResult;
+using CacheVariable = cmCMakePresetsFile::CacheVariable;
+using UnexpandedPreset = cmCMakePresetsFile::UnexpandedPreset;
+using CMakeGeneratorConfig = cmCMakePresetsFile::CMakeGeneratorConfig;
+
+constexpr int MIN_VERSION = 1;
+constexpr int MAX_VERSION = 1;
+
+struct CMakeVersion
+{
+ unsigned int Major = 0;
+ unsigned int Minor = 0;
+ unsigned int Patch = 0;
+};
+
+struct RootPresets
+{
+ CMakeVersion CMakeMinimumRequired;
+ std::vector<cmCMakePresetsFile::UnexpandedPreset> Presets;
+};
+
+cmJSONHelper<std::nullptr_t, ReadFileResult> VendorHelper(ReadFileResult error)
+{
+ return [error](std::nullptr_t& /*out*/,
+ const Json::Value* value) -> ReadFileResult {
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isObject()) {
+ return error;
+ }
+
+ return ReadFileResult::READ_OK;
+ };
+}
+
+auto const VersionIntHelper = cmJSONIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
+
+auto const VersionHelper = cmJSONRequiredHelper<int, ReadFileResult>(
+ ReadFileResult::NO_VERSION, VersionIntHelper);
+
+auto const RootVersionHelper =
+ cmJSONObjectHelper<int, ReadFileResult>(ReadFileResult::READ_OK,
+ ReadFileResult::INVALID_ROOT)
+ .Bind("version"_s, VersionHelper, false);
+
+auto const VariableStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE);
+
+auto const VariableObjectHelper =
+ cmJSONObjectHelper<CacheVariable, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VARIABLE, false)
+ .Bind("type"_s, &CacheVariable::Type, VariableStringHelper, false)
+ .Bind("value"_s, &CacheVariable::Value, VariableStringHelper);
+
+ReadFileResult VariableHelper(cm::optional<CacheVariable>& out,
+ const Json::Value* value)
+{
+ if (value->isString()) {
+ out = CacheVariable{
+ /*Type=*/"",
+ /*Value=*/value->asString(),
+ };
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isObject()) {
+ out.emplace();
+ return VariableObjectHelper(*out, value);
+ }
+ if (value->isNull()) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+ return ReadFileResult::INVALID_VARIABLE;
+}
+
+auto const VariablesHelper =
+ cmJSONMapHelper<cm::optional<CacheVariable>, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, VariableHelper);
+
+auto const PresetStringHelper = cmJSONStringHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+ReadFileResult EnvironmentHelper(cm::optional<std::string>& out,
+ const Json::Value* value)
+{
+ if (!value || value->isNull()) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+ if (value->isString()) {
+ out = value->asString();
+ return ReadFileResult::READ_OK;
+ }
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const EnvironmentMapHelper =
+ cmJSONMapHelper<cm::optional<std::string>, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ EnvironmentHelper);
+
+auto const PresetVectorStringHelper =
+ cmJSONVectorHelper<std::string, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET,
+ PresetStringHelper);
+
+ReadFileResult PresetInheritsHelper(std::vector<std::string>& out,
+ const Json::Value* value)
+{
+ out.clear();
+ if (!value) {
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->isString()) {
+ out.push_back(value->asString());
+ return ReadFileResult::READ_OK;
+ }
+
+ return PresetVectorStringHelper(out, value);
+}
+
+auto const PresetBoolHelper = cmJSONBoolHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET);
+
+auto const PresetOptionalBoolHelper =
+ cmJSONOptionalHelper<bool, ReadFileResult>(ReadFileResult::READ_OK,
+ PresetBoolHelper);
+
+auto const PresetWarningsHelper =
+ cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("dev"_s, &UnexpandedPreset::WarnDev, PresetOptionalBoolHelper, false)
+ .Bind("deprecated"_s, &UnexpandedPreset::WarnDeprecated,
+ PresetOptionalBoolHelper, false)
+ .Bind("uninitialized"_s, &UnexpandedPreset::WarnUninitialized,
+ PresetOptionalBoolHelper, false)
+ .Bind("unusedCli"_s, &UnexpandedPreset::WarnUnusedCli,
+ PresetOptionalBoolHelper, false)
+ .Bind("systemVars"_s, &UnexpandedPreset::WarnSystemVars,
+ PresetOptionalBoolHelper, false);
+
+auto const PresetErrorsHelper =
+ cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("dev"_s, &UnexpandedPreset::ErrorDev, PresetOptionalBoolHelper,
+ false)
+ .Bind("deprecated"_s, &UnexpandedPreset::ErrorDeprecated,
+ PresetOptionalBoolHelper, false);
+
+auto const PresetDebugHelper =
+ cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("output"_s, &UnexpandedPreset::DebugOutput, PresetOptionalBoolHelper,
+ false)
+ .Bind("tryCompile"_s, &UnexpandedPreset::DebugTryCompile,
+ PresetOptionalBoolHelper, false)
+ .Bind("find"_s, &UnexpandedPreset::DebugFind, PresetOptionalBoolHelper,
+ false);
+
+ReadFileResult CMakeGeneratorConfigHelper(
+ cm::optional<CMakeGeneratorConfig>& out, const Json::Value* value)
+{
+ if (!value) {
+ out = cm::nullopt;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (!value->isString()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (value->asString() == "default") {
+ out = CMakeGeneratorConfig::Default;
+ return ReadFileResult::READ_OK;
+ }
+
+ if (value->asString() == "ignore") {
+ out = CMakeGeneratorConfig::Ignore;
+ return ReadFileResult::READ_OK;
+ }
+
+ return ReadFileResult::INVALID_PRESET;
+}
+
+auto const PresetHelper =
+ cmJSONObjectHelper<UnexpandedPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESET, false)
+ .Bind("name"_s, &UnexpandedPreset::Name, PresetStringHelper)
+ .Bind("inherits"_s, &UnexpandedPreset::Inherits, PresetInheritsHelper,
+ false)
+ .Bind("hidden"_s, &UnexpandedPreset::Hidden, PresetBoolHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_PRESET), false)
+ .Bind("displayName"_s, &UnexpandedPreset::DisplayName, PresetStringHelper,
+ false)
+ .Bind("description"_s, &UnexpandedPreset::Description, PresetStringHelper,
+ false)
+ .Bind("generator"_s, &UnexpandedPreset::Generator, PresetStringHelper,
+ false)
+ .Bind("architecture"_s, &UnexpandedPreset::Architecture,
+ PresetStringHelper, false)
+ .Bind("toolset"_s, &UnexpandedPreset::Toolset, PresetStringHelper, false)
+ .Bind("cmakeGeneratorConfig"_s, &UnexpandedPreset::GeneratorConfig,
+ CMakeGeneratorConfigHelper, false)
+ .Bind("binaryDir"_s, &UnexpandedPreset::BinaryDir, PresetStringHelper,
+ false)
+ .Bind<std::string>("cmakeExecutable"_s, nullptr, PresetStringHelper, false)
+ .Bind("cacheVariables"_s, &UnexpandedPreset::CacheVariables,
+ VariablesHelper, false)
+ .Bind("environment"_s, &UnexpandedPreset::Environment,
+ EnvironmentMapHelper, false)
+ .Bind("warnings"_s, PresetWarningsHelper, false)
+ .Bind("errors"_s, PresetErrorsHelper, false)
+ .Bind("debug"_s, PresetDebugHelper, false);
+
+auto const PresetsHelper =
+ cmJSONVectorHelper<UnexpandedPreset, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_PRESETS, PresetHelper);
+
+auto const CMakeVersionUIntHelper = cmJSONUIntHelper<ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_VERSION);
+
+auto const CMakeVersionHelper =
+ cmJSONObjectHelper<CMakeVersion, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_CMAKE_VERSION, false)
+ .Bind("major"_s, &CMakeVersion::Major, CMakeVersionUIntHelper, false)
+ .Bind("minor"_s, &CMakeVersion::Minor, CMakeVersionUIntHelper, false)
+ .Bind("patch"_s, &CMakeVersion::Patch, CMakeVersionUIntHelper, false);
+
+auto const RootPresetsHelper =
+ cmJSONObjectHelper<RootPresets, ReadFileResult>(
+ ReadFileResult::READ_OK, ReadFileResult::INVALID_ROOT, false)
+ .Bind<int>("version"_s, nullptr, VersionHelper)
+ .Bind("configurePresets"_s, &RootPresets::Presets, PresetsHelper, false)
+ .Bind("cmakeMinimumRequired"_s, &RootPresets::CMakeMinimumRequired,
+ CMakeVersionHelper, false)
+ .Bind<std::nullptr_t>("vendor"_s, nullptr,
+ VendorHelper(ReadFileResult::INVALID_ROOT), false);
+
+void InheritString(std::string& child, const std::string& parent)
+{
+ if (child.empty()) {
+ child = parent;
+ }
+}
+
+void InheritOptionalBool(cm::optional<bool>& child,
+ const cm::optional<bool>& parent)
+{
+ if (!child) {
+ child = parent;
+ }
+}
+
+/**
+ * Check preset inheritance for cycles (using a DAG check algorithm) while
+ * also bubbling up fields through the inheritance hierarchy, then verify
+ * that each preset has the required fields, either directly or through
+ * inheritance.
+ */
+ReadFileResult VisitPreset(std::map<std::string, UnexpandedPreset>& presets,
+ UnexpandedPreset& preset,
+ std::map<std::string, CycleStatus> cycleStatus)
+{
+ switch (cycleStatus[preset.Name]) {
+ case CycleStatus::InProgress:
+ return ReadFileResult::CYCLIC_PRESET_INHERITANCE;
+ case CycleStatus::Verified:
+ return ReadFileResult::READ_OK;
+ default:
+ break;
+ }
+
+ cycleStatus[preset.Name] = CycleStatus::InProgress;
+
+ for (auto const& i : preset.Inherits) {
+ auto parent = presets.find(i);
+ if (parent == presets.end()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+
+ if (!preset.User && parent->second.User) {
+ return ReadFileResult::USER_PRESET_INHERITANCE;
+ }
+
+ auto result = VisitPreset(presets, parent->second, cycleStatus);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+
+ InheritString(preset.Generator, parent->second.Generator);
+ InheritString(preset.Architecture, parent->second.Architecture);
+ InheritString(preset.Toolset, parent->second.Toolset);
+ if (!preset.GeneratorConfig) {
+ preset.GeneratorConfig = parent->second.GeneratorConfig;
+ }
+ InheritString(preset.BinaryDir, parent->second.BinaryDir);
+ InheritOptionalBool(preset.WarnDev, parent->second.WarnDev);
+ InheritOptionalBool(preset.ErrorDev, parent->second.ErrorDev);
+ InheritOptionalBool(preset.WarnDeprecated, parent->second.WarnDeprecated);
+ InheritOptionalBool(preset.ErrorDeprecated,
+ parent->second.ErrorDeprecated);
+ InheritOptionalBool(preset.WarnUninitialized,
+ parent->second.WarnUninitialized);
+ InheritOptionalBool(preset.WarnUnusedCli, parent->second.WarnUnusedCli);
+ InheritOptionalBool(preset.WarnSystemVars, parent->second.WarnSystemVars);
+ for (auto const& v : parent->second.CacheVariables) {
+ preset.CacheVariables.insert(v);
+ }
+ for (auto const& v : parent->second.Environment) {
+ preset.Environment.insert(v);
+ }
+ }
+
+ if (!preset.Hidden) {
+ if (preset.Generator.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ if (preset.BinaryDir.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ if (preset.WarnDev == false && preset.ErrorDev == true) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ if (preset.WarnDeprecated == false && preset.ErrorDeprecated == true) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ }
+
+ cycleStatus[preset.Name] = CycleStatus::Verified;
+ return ReadFileResult::READ_OK;
+}
+
+ReadFileResult ComputePresetInheritance(
+ std::map<std::string, UnexpandedPreset>& presets)
+{
+ std::map<std::string, CycleStatus> cycleStatus;
+ for (auto const& it : presets) {
+ cycleStatus[it.first] = CycleStatus::Unvisited;
+ }
+
+ for (auto& it : presets) {
+ auto result = VisitPreset(presets, it.second, cycleStatus);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ }
+
+ return ReadFileResult::READ_OK;
+}
+
+constexpr const char* ValidPrefixes[] = {
+ "",
+ "env",
+ "penv",
+ "vendor",
+};
+
+bool PrefixesValidMacroNamespace(const std::string& str)
+{
+ for (auto const& prefix : ValidPrefixes) {
+ if (cmHasPrefix(prefix, str)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool IsValidMacroNamespace(const std::string& str)
+{
+ for (auto const& prefix : ValidPrefixes) {
+ if (str == prefix) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool VisitEnv(const cmCMakePresetsFile& file,
+ cmCMakePresetsFile::ExpandedPreset& preset,
+ std::map<std::string, CycleStatus>& envCycles,
+ std::string& value, CycleStatus& status);
+bool ExpandMacros(const cmCMakePresetsFile& file,
+ cmCMakePresetsFile::ExpandedPreset& preset,
+ std::map<std::string, CycleStatus>& envCycles,
+ std::string& out);
+bool ExpandMacro(const cmCMakePresetsFile& file,
+ cmCMakePresetsFile::ExpandedPreset& preset,
+ std::map<std::string, CycleStatus>& envCycles,
+ std::string& out, const std::string& macroNamespace,
+ const std::string& macroName);
+
+bool VisitEnv(const cmCMakePresetsFile& file,
+ cmCMakePresetsFile::ExpandedPreset& preset,
+ std::map<std::string, CycleStatus>& envCycles,
+ std::string& value, CycleStatus& status)
+{
+ if (status == CycleStatus::Verified) {
+ return true;
+ }
+ if (status == CycleStatus::InProgress) {
+ return false;
+ }
+
+ status = CycleStatus::InProgress;
+ if (!ExpandMacros(file, preset, envCycles, value)) {
+ return false;
+ }
+ status = CycleStatus::Verified;
+ return true;
+}
+
+bool ExpandMacros(const cmCMakePresetsFile& file,
+ cmCMakePresetsFile::ExpandedPreset& preset,
+ std::map<std::string, CycleStatus>& envCycles,
+ std::string& out)
+{
+ std::string result;
+ std::string macroNamespace;
+ std::string macroName;
+
+ enum class State
+ {
+ Default,
+ MacroNamespace,
+ MacroName,
+ } state = State::Default;
+
+ for (auto c : out) {
+ switch (state) {
+ case State::Default:
+ if (c == '$') {
+ state = State::MacroNamespace;
+ } else {
+ result += c;
+ }
+ break;
+
+ case State::MacroNamespace:
+ if (c == '{') {
+ if (IsValidMacroNamespace(macroNamespace)) {
+ state = State::MacroName;
+ } else {
+ result += '$';
+ result += macroNamespace;
+ result += '{';
+ macroNamespace.clear();
+ state = State::Default;
+ }
+ } else {
+ macroNamespace += c;
+ if (!PrefixesValidMacroNamespace(macroNamespace)) {
+ result += '$';
+ result += macroNamespace;
+ macroNamespace.clear();
+ state = State::Default;
+ }
+ }
+ break;
+
+ case State::MacroName:
+ if (c == '}') {
+ if (!ExpandMacro(file, preset, envCycles, result, macroNamespace,
+ macroName)) {
+ return false;
+ }
+ macroNamespace.clear();
+ macroName.clear();
+ state = State::Default;
+ } else {
+ macroName += c;
+ }
+ break;
+ }
+ }
+
+ switch (state) {
+ case State::Default:
+ break;
+ case State::MacroNamespace:
+ result += '$';
+ result += macroNamespace;
+ break;
+ case State::MacroName:
+ return false;
+ }
+
+ out = std::move(result);
+ return true;
+}
+
+bool ExpandMacro(const cmCMakePresetsFile& file,
+ cmCMakePresetsFile::ExpandedPreset& preset,
+ std::map<std::string, CycleStatus>& envCycles,
+ std::string& out, const std::string& macroNamespace,
+ const std::string& macroName)
+{
+ if (macroNamespace.empty()) {
+ if (macroName == "sourceDir") {
+ out += file.SourceDir;
+ return true;
+ }
+ if (macroName == "sourceParentDir") {
+ out += cmSystemTools::GetParentDirectory(file.SourceDir);
+ return true;
+ }
+ if (macroName == "presetName") {
+ out += preset.Name;
+ return true;
+ }
+ if (macroName == "generator") {
+ out += preset.Generator;
+ return true;
+ }
+ if (macroName == "dollar") {
+ out += '$';
+ return true;
+ }
+ }
+
+ if (macroNamespace == "env") {
+ auto v = preset.Environment.find(macroName);
+ if (v != preset.Environment.end() && v->second) {
+ if (!VisitEnv(file, preset, envCycles, *v->second,
+ envCycles[macroName])) {
+ return false;
+ }
+ out += *v->second;
+ return true;
+ }
+ }
+
+ if (macroNamespace == "env" || macroNamespace == "penv") {
+ const char* value = std::getenv(macroName.c_str());
+ if (value) {
+ out += value;
+ }
+ return true;
+ }
+
+ // "vendor" falls through to here
+ return false;
+}
+}
+
+std::string cmCMakePresetsFile::GetFilename(const std::string& sourceDir)
+{
+ return cmStrCat(sourceDir, "/CMakePresets.json");
+}
+
+std::string cmCMakePresetsFile::GetUserFilename(const std::string& sourceDir)
+{
+ return cmStrCat(sourceDir, "/CMakeUserPresets.json");
+}
+
+cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadProjectPresets(
+ const std::string& sourceDir, bool allowNoFiles)
+{
+ bool haveOneFile = false;
+ this->SourceDir = sourceDir;
+ this->Presets.clear();
+ this->PresetOrder.clear();
+
+ std::vector<std::string> presetOrder;
+ std::map<std::string, UnexpandedPreset> presetMap;
+
+ std::string filename = GetUserFilename(this->SourceDir);
+ if (cmSystemTools::FileExists(filename)) {
+ auto result = this->ReadJSONFile(filename, presetOrder, presetMap, true);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ haveOneFile = true;
+ }
+
+ filename = GetFilename(this->SourceDir);
+ if (cmSystemTools::FileExists(filename)) {
+ auto result = this->ReadJSONFile(filename, presetOrder, presetMap, false);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ haveOneFile = true;
+ }
+
+ if (!haveOneFile) {
+ return allowNoFiles ? ReadFileResult::READ_OK
+ : ReadFileResult::FILE_NOT_FOUND;
+ }
+
+ auto result = ComputePresetInheritance(presetMap);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+
+ this->PresetOrder = std::move(presetOrder);
+ this->Presets = std::move(presetMap);
+ return ReadFileResult::READ_OK;
+}
+
+const char* cmCMakePresetsFile::ResultToString(ReadFileResult result)
+{
+ switch (result) {
+ case ReadFileResult::READ_OK:
+ return "OK";
+ case ReadFileResult::FILE_NOT_FOUND:
+ return "File not found";
+ case ReadFileResult::JSON_PARSE_ERROR:
+ return "JSON parse error";
+ case ReadFileResult::INVALID_ROOT:
+ return "Invalid root object";
+ case ReadFileResult::NO_VERSION:
+ return "No \"version\" field";
+ case ReadFileResult::INVALID_VERSION:
+ return "Invalid \"version\" field";
+ case ReadFileResult::UNRECOGNIZED_VERSION:
+ return "Unrecognized \"version\" field";
+ case ReadFileResult::INVALID_CMAKE_VERSION:
+ return "Invalid \"cmakeMinimumRequired\" field";
+ case ReadFileResult::UNRECOGNIZED_CMAKE_VERSION:
+ return "\"cmakeMinimumRequired\" version too new";
+ case ReadFileResult::INVALID_PRESETS:
+ return "Invalid \"configurePresets\" field";
+ case ReadFileResult::INVALID_PRESET:
+ return "Invalid preset";
+ case ReadFileResult::INVALID_VARIABLE:
+ return "Invalid CMake variable definition";
+ case ReadFileResult::DUPLICATE_PRESETS:
+ return "Duplicate presets";
+ case ReadFileResult::CYCLIC_PRESET_INHERITANCE:
+ return "Cyclic preset inheritance";
+ case ReadFileResult::USER_PRESET_INHERITANCE:
+ return "Project preset inherits from user preset";
+ default:
+ return "Unknown error";
+ }
+}
+
+cm::optional<cmCMakePresetsFile::ExpandedPreset>
+cmCMakePresetsFile::ExpandMacros(const UnexpandedPreset& preset) const
+{
+ ExpandedPreset retval{ preset };
+
+ std::map<std::string, CycleStatus> envCycles;
+ for (auto const& v : retval.Environment) {
+ envCycles[v.first] = CycleStatus::Unvisited;
+ }
+
+ for (auto& v : retval.Environment) {
+ if (v.second &&
+ !VisitEnv(*this, retval, envCycles, *v.second, envCycles[v.first])) {
+ return cm::nullopt;
+ }
+ }
+
+ std::string binaryDir = preset.BinaryDir;
+ if (!::ExpandMacros(*this, retval, envCycles, binaryDir)) {
+ return cm::nullopt;
+ }
+ if (!cmSystemTools::FileIsFullPath(binaryDir)) {
+ binaryDir = cmStrCat(this->SourceDir, '/', binaryDir);
+ }
+ retval.BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
+ cmSystemTools::ConvertToUnixSlashes(retval.BinaryDir);
+
+ for (auto& variable : retval.CacheVariables) {
+ if (variable.second &&
+ !::ExpandMacros(*this, retval, envCycles, variable.second->Value)) {
+ return cm::nullopt;
+ }
+ }
+
+ return cm::make_optional(retval);
+}
+
+cmCMakePresetsFile::ReadFileResult cmCMakePresetsFile::ReadJSONFile(
+ const std::string& filename, std::vector<std::string>& presetOrder,
+ std::map<std::string, UnexpandedPreset>& presetMap, bool user)
+{
+ cmsys::ifstream fin(filename.c_str());
+ if (!fin) {
+ return ReadFileResult::FILE_NOT_FOUND;
+ }
+ // If there's a BOM, toss it.
+ cmsys::FStream::ReadBOM(fin);
+
+ Json::Value root;
+ Json::CharReaderBuilder builder;
+ if (!Json::parseFromStream(builder, fin, &root, nullptr)) {
+ return ReadFileResult::JSON_PARSE_ERROR;
+ }
+
+ int v = 0;
+ auto result = RootVersionHelper(v, &root);
+ if (result != ReadFileResult::READ_OK) {
+ return result;
+ }
+ if (v < MIN_VERSION || v > MAX_VERSION) {
+ return ReadFileResult::UNRECOGNIZED_VERSION;
+ }
+
+ RootPresets presets;
+ if ((result = RootPresetsHelper(presets, &root)) !=
+ ReadFileResult::READ_OK) {
+ return result;
+ }
+
+ unsigned int currentMajor = cmVersion::GetMajorVersion();
+ unsigned int currentMinor = cmVersion::GetMinorVersion();
+ unsigned int currentPatch = cmVersion::GetPatchVersion();
+ auto const& required = presets.CMakeMinimumRequired;
+ if (required.Major > currentMajor ||
+ (required.Major == currentMajor &&
+ (required.Minor > currentMinor ||
+ (required.Minor == currentMinor &&
+ (required.Patch > currentPatch))))) {
+ return ReadFileResult::UNRECOGNIZED_CMAKE_VERSION;
+ }
+
+ for (auto& preset : presets.Presets) {
+ preset.User = user;
+ if (preset.Name.empty()) {
+ return ReadFileResult::INVALID_PRESET;
+ }
+ if (!presetMap.insert({ preset.Name, preset }).second) {
+ return ReadFileResult::DUPLICATE_PRESETS;
+ }
+ presetOrder.push_back(preset.Name);
+ }
+
+ return ReadFileResult::READ_OK;
+}
diff --git a/Source/cmCMakePresetsFile.h b/Source/cmCMakePresetsFile.h
new file mode 100644
index 0000000..70ec4c5
--- /dev/null
+++ b/Source/cmCMakePresetsFile.h
@@ -0,0 +1,141 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <cm/optional>
+
+class cmCMakePresetsFile
+{
+public:
+ enum class CMakeGeneratorConfig
+ {
+ Default,
+ Ignore,
+ };
+
+ class CacheVariable
+ {
+ public:
+ std::string Type;
+ std::string Value;
+ };
+
+ class Preset
+ {
+ public:
+#if __cplusplus < 201703L && (!defined(_MSVC_LANG) || _MSVC_LANG < 201703L)
+ Preset() = default;
+ Preset(const Preset& /*other*/) = default;
+ Preset(Preset&& /*other*/) = default;
+
+ Preset& operator=(const Preset& /*other*/) = default;
+
+ // The move assignment operators for several STL classes did not become
+ // noexcept until C++17, which causes some tools to warn about this move
+ // assignment operator throwing an exception when it shouldn't. Disable the
+ // move assignment operator until C++17 is enabled.
+ Preset& operator=(Preset&& /*other*/) = delete;
+#endif
+
+ std::string Name;
+ std::vector<std::string> Inherits;
+ bool Hidden;
+ bool User;
+ std::string DisplayName;
+ std::string Description;
+ std::string Generator;
+ std::string Architecture;
+ std::string Toolset;
+ cm::optional<CMakeGeneratorConfig> GeneratorConfig;
+ std::string BinaryDir;
+
+ std::map<std::string, cm::optional<CacheVariable>> CacheVariables;
+ std::map<std::string, cm::optional<std::string>> Environment;
+
+ cm::optional<bool> WarnDev;
+ cm::optional<bool> ErrorDev;
+ cm::optional<bool> WarnDeprecated;
+ cm::optional<bool> ErrorDeprecated;
+ cm::optional<bool> WarnUninitialized;
+ cm::optional<bool> WarnUnusedCli;
+ cm::optional<bool> WarnSystemVars;
+
+ cm::optional<bool> DebugOutput;
+ cm::optional<bool> DebugTryCompile;
+ cm::optional<bool> DebugFind;
+ };
+
+ class UnexpandedPreset : public Preset
+ {
+ public:
+ using Preset::Preset;
+
+ UnexpandedPreset() = default;
+ UnexpandedPreset(const Preset& preset)
+ : Preset(preset)
+ {
+ }
+ UnexpandedPreset(Preset&& preset)
+ : Preset(std::move(preset))
+ {
+ }
+ };
+
+ class ExpandedPreset : public Preset
+ {
+ public:
+ using Preset::Preset;
+
+ ExpandedPreset() = default;
+ ExpandedPreset(const Preset& preset)
+ : Preset(preset)
+ {
+ }
+ ExpandedPreset(Preset&& preset)
+ : Preset(std::move(preset))
+ {
+ }
+ };
+
+ std::string SourceDir;
+ std::map<std::string, UnexpandedPreset> Presets;
+ std::vector<std::string> PresetOrder;
+
+ enum class ReadFileResult
+ {
+ READ_OK,
+ FILE_NOT_FOUND,
+ JSON_PARSE_ERROR,
+ INVALID_ROOT,
+ NO_VERSION,
+ INVALID_VERSION,
+ UNRECOGNIZED_VERSION,
+ INVALID_CMAKE_VERSION,
+ UNRECOGNIZED_CMAKE_VERSION,
+ INVALID_PRESETS,
+ INVALID_PRESET,
+ INVALID_VARIABLE,
+ DUPLICATE_PRESETS,
+ CYCLIC_PRESET_INHERITANCE,
+ USER_PRESET_INHERITANCE,
+ };
+
+ static std::string GetFilename(const std::string& sourceDir);
+ static std::string GetUserFilename(const std::string& sourceDir);
+ ReadFileResult ReadProjectPresets(const std::string& sourceDir,
+ bool allowNoFiles = false);
+ static const char* ResultToString(ReadFileResult result);
+
+ cm::optional<ExpandedPreset> ExpandMacros(
+ const UnexpandedPreset& preset) const;
+
+private:
+ ReadFileResult ReadJSONFile(
+ const std::string& filename, std::vector<std::string>& presetOrder,
+ std::map<std::string, UnexpandedPreset>& presetMap, bool user);
+};
diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h
index 3a7f806..d6ababb 100644
--- a/Source/cmGlobalGeneratorFactory.h
+++ b/Source/cmGlobalGeneratorFactory.h
@@ -25,7 +25,7 @@ public:
/** Create a GlobalGenerator */
virtual std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& n, cmake* cm) const = 0;
+ const std::string& n, bool allowArch, cmake* cm) const = 0;
/** Get the documentation entry for this factory */
virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0;
@@ -53,7 +53,7 @@ class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory
public:
/** Create a GlobalGenerator */
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override
+ const std::string& name, bool /*allowArch*/, cmake* cm) const override
{
if (name != T::GetActualName()) {
return std::unique_ptr<cmGlobalGenerator>();
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 3805546..7794df3 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -59,7 +59,7 @@ class cmGlobalVisualStudio10Generator::Factory
{
public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override
+ const std::string& name, bool allowArch, cmake* cm) const override
{
std::string genName;
const char* p = cmVS10GenName(name, genName);
@@ -70,7 +70,7 @@ public:
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudio10Generator(cm, genName, ""));
}
- if (*p++ != ' ') {
+ if (!allowArch || *p++ != ' ') {
return std::unique_ptr<cmGlobalGenerator>();
}
if (strcmp(p, "Win64") == 0) {
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index a385375..a5ffcf0 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -31,7 +31,7 @@ class cmGlobalVisualStudio11Generator::Factory
{
public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override
+ const std::string& name, bool allowArch, cmake* cm) const override
{
std::string genName;
const char* p = cmVS11GenName(name, genName);
@@ -42,7 +42,7 @@ public:
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudio11Generator(cm, genName, ""));
}
- if (*p++ != ' ') {
+ if (!allowArch || *p++ != ' ') {
return std::unique_ptr<cmGlobalGenerator>();
}
if (strcmp(p, "Win64") == 0) {
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index 5a27994..8bdf356 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -29,7 +29,7 @@ class cmGlobalVisualStudio12Generator::Factory
{
public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override
+ const std::string& name, bool allowArch, cmake* cm) const override
{
std::string genName;
const char* p = cmVS12GenName(name, genName);
@@ -40,7 +40,7 @@ public:
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudio12Generator(cm, genName, ""));
}
- if (*p++ != ' ') {
+ if (!allowArch || *p++ != ' ') {
return std::unique_ptr<cmGlobalGenerator>();
}
if (strcmp(p, "Win64") == 0) {
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index a12b7e1..e17c6d7 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -30,7 +30,7 @@ class cmGlobalVisualStudio14Generator::Factory
{
public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override
+ const std::string& name, bool allowArch, cmake* cm) const override
{
std::string genName;
const char* p = cmVS14GenName(name, genName);
@@ -41,7 +41,7 @@ public:
return std::unique_ptr<cmGlobalGenerator>(
new cmGlobalVisualStudio14Generator(cm, genName, ""));
}
- if (*p++ != ' ') {
+ if (!allowArch || *p++ != ' ') {
return std::unique_ptr<cmGlobalGenerator>();
}
if (strcmp(p, "Win64") == 0) {
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index 9f73c15..2339a80 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -16,7 +16,7 @@ class cmGlobalVisualStudio9Generator::Factory : public cmGlobalGeneratorFactory
{
public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override
+ const std::string& name, bool allowArch, cmake* cm) const override
{
if (strncmp(name.c_str(), vs9generatorName,
sizeof(vs9generatorName) - 1) != 0) {
@@ -29,7 +29,7 @@ public:
new cmGlobalVisualStudio9Generator(cm, name, ""));
}
- if (p[0] != ' ') {
+ if (!allowArch || p[0] != ' ') {
return std::unique_ptr<cmGlobalGenerator>();
}
diff --git a/Source/cmGlobalVisualStudioVersionedGenerator.cxx b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
index 4b877ce..95357e7 100644
--- a/Source/cmGlobalVisualStudioVersionedGenerator.cxx
+++ b/Source/cmGlobalVisualStudioVersionedGenerator.cxx
@@ -140,7 +140,7 @@ class cmGlobalVisualStudioVersionedGenerator::Factory15
{
public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override
+ const std::string& name, bool allowArch, cmake* cm) const override
{
std::string genName;
const char* p = cmVS15GenName(name, genName);
@@ -152,7 +152,7 @@ public:
new cmGlobalVisualStudioVersionedGenerator(
cmGlobalVisualStudioGenerator::VS15, cm, genName, ""));
}
- if (*p++ != ' ') {
+ if (!allowArch || *p++ != ' ') {
return std::unique_ptr<cmGlobalGenerator>();
}
if (strcmp(p, "Win64") == 0) {
@@ -234,7 +234,7 @@ class cmGlobalVisualStudioVersionedGenerator::Factory16
{
public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override
+ const std::string& name, bool /*allowArch*/, cmake* cm) const override
{
std::string genName;
const char* p = cmVS16GenName(name, genName);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index f1a1ce6..952a179 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -135,7 +135,7 @@ class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory
{
public:
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name, cmake* cm) const override;
+ const std::string& name, bool allowArch, cmake* cm) const override;
void GetDocumentation(cmDocumentationEntry& entry) const override
{
@@ -197,6 +197,7 @@ std::unique_ptr<cmGlobalGeneratorFactory> cmGlobalXCodeGenerator::NewFactory()
std::unique_ptr<cmGlobalGenerator>
cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(const std::string& name,
+ bool /*allowArch*/,
cmake* cm) const
{
if (name != GetActualName()) {
diff --git a/Source/cmJSONHelpers.h b/Source/cmJSONHelpers.h
index 2da2a03..a63347d 100644
--- a/Source/cmJSONHelpers.h
+++ b/Source/cmJSONHelpers.h
@@ -29,6 +29,9 @@ public:
template <typename M, typename F>
cmJSONObjectHelper& Bind(const cm::string_view& name, std::nullptr_t, F func,
bool required = true);
+ template <typename F>
+ cmJSONObjectHelper& Bind(const cm::string_view& name, F func,
+ bool required = true);
E operator()(T& out, const Json::Value* value) const;
@@ -87,6 +90,14 @@ cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind(
}
template <typename T, typename E>
+template <typename F>
+cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::Bind(
+ const cm::string_view& name, F func, bool required)
+{
+ return this->BindPrivate(name, MemberFunction(func), required);
+}
+
+template <typename T, typename E>
cmJSONObjectHelper<T, E>& cmJSONObjectHelper<T, E>::BindPrivate(
const cm::string_view& name, MemberFunction&& func, bool required)
{
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index d9c6b7a..2a14b03 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -13,6 +13,7 @@
#include <utility>
#include <cm/memory>
+#include <cm/optional>
#include <cm/string_view>
#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW)
# include <cm/iterator>
@@ -27,6 +28,7 @@
#include "cm_sys_stat.h"
+#include "cmCMakePresetsFile.h"
#include "cmCommands.h"
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
@@ -286,6 +288,97 @@ void cmake::CleanupCommandsAndMacros()
this->CurrentSnapshot.SetDefaultDefinitions();
}
+#ifndef CMAKE_BOOTSTRAP
+void cmake::SetWarningFromPreset(const std::string& name,
+ const cm::optional<bool>& warning,
+ const cm::optional<bool>& error)
+{
+ if (warning) {
+ if (*warning) {
+ this->DiagLevels[name] = std::max(this->DiagLevels[name], DIAG_WARN);
+ } else {
+ this->DiagLevels[name] = DIAG_IGNORE;
+ }
+ }
+ if (error) {
+ if (*error) {
+ this->DiagLevels[name] = DIAG_ERROR;
+ } else {
+ this->DiagLevels[name] = std::min(this->DiagLevels[name], DIAG_WARN);
+ }
+ }
+}
+
+void cmake::ProcessPresetVariables()
+{
+ for (auto const& var : this->UnprocessedPresetVariables) {
+ if (!var.second) {
+ continue;
+ }
+ cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
+ if (!var.second->Type.empty()) {
+ type = cmState::StringToCacheEntryType(var.second->Type);
+ }
+ this->ProcessCacheArg(var.first, var.second->Value, type);
+ }
+}
+
+void cmake::PrintPresetVariables()
+{
+ bool first = true;
+ for (auto const& var : this->UnprocessedPresetVariables) {
+ if (!var.second) {
+ continue;
+ }
+ cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
+ if (!var.second->Type.empty()) {
+ type = cmState::StringToCacheEntryType(var.second->Type);
+ }
+ if (first) {
+ std::cout << "Preset CMake variables:\n\n";
+ first = false;
+ }
+ std::cout << " " << var.first;
+ if (type != cmStateEnums::UNINITIALIZED) {
+ std::cout << ':' << cmState::CacheEntryTypeToString(type);
+ }
+ std::cout << "=\"" << var.second->Value << "\"\n";
+ }
+ if (!first) {
+ std::cout << '\n';
+ }
+ this->UnprocessedPresetVariables.clear();
+}
+
+void cmake::ProcessPresetEnvironment()
+{
+ for (auto const& var : this->UnprocessedPresetEnvironment) {
+ if (var.second) {
+ cmSystemTools::PutEnv(cmStrCat(var.first, '=', *var.second));
+ }
+ }
+}
+
+void cmake::PrintPresetEnvironment()
+{
+ bool first = true;
+ for (auto const& var : this->UnprocessedPresetEnvironment) {
+ if (!var.second) {
+ continue;
+ }
+ if (first) {
+ std::cout << "Preset environment variables:\n\n";
+ first = false;
+ }
+ std::cout << " " << var.first << "=\"" << *var.second << "\"\n";
+ }
+ if (!first) {
+ std::cout << '\n';
+ }
+ this->UnprocessedPresetEnvironment.clear();
+}
+#endif
+
// Parse the args
bool cmake::SetCacheArgs(const std::vector<std::string>& args)
{
@@ -308,28 +401,10 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
std::string value;
cmStateEnums::CacheEntryType type = cmStateEnums::UNINITIALIZED;
if (cmState::ParseCacheEntry(entry, var, value, type)) {
- // The value is transformed if it is a filepath for example, so
- // we can't compare whether the value is already in the cache until
- // after we call AddCacheEntry.
- bool haveValue = false;
- std::string cachedValue;
- if (this->WarnUnusedCli) {
- if (cmProp v = this->State->GetInitializedCacheValue(var)) {
- haveValue = true;
- cachedValue = *v;
- }
- }
-
- this->AddCacheEntry(var, value.c_str(),
- "No help, variable specified on the command line.",
- type);
-
- if (this->WarnUnusedCli) {
- if (!haveValue ||
- cachedValue != *this->State->GetInitializedCacheValue(var)) {
- this->WatchUnusedCli(var);
- }
- }
+#ifndef CMAKE_BOOTSTRAP
+ this->UnprocessedPresetVariables.erase(var);
+#endif
+ this->ProcessCacheArg(var, value, type);
} else {
cmSystemTools::Error("Parse error in command line argument: " + arg +
"\n" + "Should be: VAR:type=value\n");
@@ -409,6 +484,9 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
// now remove them from the cache
for (std::string const& currentEntry : entriesToDelete) {
+#ifndef CMAKE_BOOTSTRAP
+ this->UnprocessedPresetVariables.erase(currentEntry);
+#endif
this->State->RemoveCacheEntry(currentEntry);
}
} else if (cmHasLiteralPrefix(arg, "-C")) {
@@ -462,6 +540,33 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args)
return true;
}
+void cmake::ProcessCacheArg(const std::string& var, const std::string& value,
+ cmStateEnums::CacheEntryType type)
+{
+ // The value is transformed if it is a filepath for example, so
+ // we can't compare whether the value is already in the cache until
+ // after we call AddCacheEntry.
+ bool haveValue = false;
+ std::string cachedValue;
+ if (this->WarnUnusedCli) {
+ if (cmProp v = this->State->GetInitializedCacheValue(var)) {
+ haveValue = true;
+ cachedValue = *v;
+ }
+ }
+
+ this->AddCacheEntry(var, value.c_str(),
+ "No help, variable specified on the command line.",
+ type);
+
+ if (this->WarnUnusedCli) {
+ if (!haveValue ||
+ cachedValue != *this->State->GetInitializedCacheValue(var)) {
+ this->WatchUnusedCli(var);
+ }
+ }
+}
+
void cmake::ReadListFile(const std::vector<std::string>& args,
const std::string& path)
{
@@ -625,6 +730,8 @@ void cmake::SetArgs(const std::vector<std::string>& args)
#if !defined(CMAKE_BOOTSTRAP)
std::string profilingFormat;
std::string profilingOutput;
+ std::string presetName;
+ bool listPresets = false;
#endif
for (unsigned int i = 1; i < args.size(); ++i) {
std::string const& arg = args[i];
@@ -830,19 +937,9 @@ void cmake::SetArgs(const std::vector<std::string>& args)
}
value = args[i];
}
- auto gen = this->CreateGlobalGenerator(value);
- if (!gen) {
- std::string kdevError;
- if (value.find("KDevelop3", 0) != std::string::npos) {
- kdevError = "\nThe KDevelop3 generator is not supported anymore.";
- }
-
- cmSystemTools::Error(
- cmStrCat("Could not create named generator ", value, kdevError));
- this->PrintGeneratorList();
+ if (!this->CreateAndSetGlobalGenerator(value, true)) {
return;
}
- this->SetGlobalGenerator(std::move(gen));
#if !defined(CMAKE_BOOTSTRAP)
} else if (cmHasLiteralPrefix(arg, "--profiling-format")) {
profilingFormat = arg.substr(strlen("--profiling-format="));
@@ -856,6 +953,13 @@ void cmake::SetArgs(const std::vector<std::string>& args)
if (profilingOutput.empty()) {
cmSystemTools::Error("No path specified for --profiling-output");
}
+ } else if (cmHasLiteralPrefix(arg, "--preset")) {
+ presetName = arg.substr(strlen("--preset="));
+ if (presetName.empty()) {
+ cmSystemTools::Error("No preset specified for --preset");
+ }
+ } else if (cmHasLiteralPrefix(arg, "--list-presets")) {
+ listPresets = true;
#endif
}
// no option assume it is the path to the source or an existing build
@@ -915,6 +1019,91 @@ void cmake::SetArgs(const std::vector<std::string>& args)
if (!haveBinaryDir) {
this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
}
+
+#if !defined(CMAKE_BOOTSTRAP)
+ if (listPresets || !presetName.empty()) {
+ cmCMakePresetsFile settingsFile;
+ auto result = settingsFile.ReadProjectPresets(this->GetHomeDirectory());
+ if (result != cmCMakePresetsFile::ReadFileResult::READ_OK) {
+ cmSystemTools::Error(
+ cmStrCat("Could not read presets from ", this->GetHomeDirectory(),
+ ": ", cmCMakePresetsFile::ResultToString(result)));
+ return;
+ }
+ if (listPresets) {
+ this->PrintPresetList(settingsFile);
+ return;
+ }
+ auto preset = settingsFile.Presets.find(presetName);
+ if (preset == settingsFile.Presets.end()) {
+ cmSystemTools::Error(cmStrCat("No such preset in ",
+ this->GetHomeDirectory(), ": \"",
+ presetName, '"'));
+ this->PrintPresetList(settingsFile);
+ return;
+ }
+ if (preset->second.Hidden) {
+ cmSystemTools::Error(cmStrCat("Cannot use hidden preset in ",
+ this->GetHomeDirectory(), ": \"",
+ presetName, '"'));
+ this->PrintPresetList(settingsFile);
+ return;
+ }
+ auto expandedPreset = settingsFile.ExpandMacros(preset->second);
+ if (!expandedPreset) {
+ cmSystemTools::Error(cmStrCat("Could not evaluate preset \"",
+ preset->second.Name,
+ "\": Invalid macro expansion"));
+ return;
+ }
+
+ if (!haveBinaryDir) {
+ this->SetHomeOutputDirectory(expandedPreset->BinaryDir);
+ }
+ if (!this->GlobalGenerator) {
+ if (!this->CreateAndSetGlobalGenerator(expandedPreset->Generator,
+ false)) {
+ return;
+ }
+ }
+ this->UnprocessedPresetVariables = expandedPreset->CacheVariables;
+ this->UnprocessedPresetEnvironment = expandedPreset->Environment;
+
+ if (!expandedPreset->GeneratorConfig ||
+ expandedPreset->GeneratorConfig ==
+ cmCMakePresetsFile::CMakeGeneratorConfig::Default) {
+ if (!this->GeneratorPlatformSet) {
+ this->SetGeneratorPlatform(expandedPreset->Architecture);
+ }
+ if (!this->GeneratorToolsetSet) {
+ this->SetGeneratorToolset(expandedPreset->Toolset);
+ }
+ }
+
+ this->SetWarningFromPreset("dev", expandedPreset->WarnDev,
+ expandedPreset->ErrorDev);
+ this->SetWarningFromPreset("deprecated", expandedPreset->WarnDeprecated,
+ expandedPreset->ErrorDeprecated);
+ if (expandedPreset->WarnUninitialized == true) {
+ this->SetWarnUninitialized(true);
+ }
+ if (expandedPreset->WarnUnusedCli == false) {
+ this->SetWarnUnusedCli(false);
+ }
+ if (expandedPreset->WarnSystemVars == true) {
+ this->SetCheckSystemVars(true);
+ }
+ if (expandedPreset->DebugOutput == true) {
+ this->SetDebugOutputOn(true);
+ }
+ if (expandedPreset->DebugTryCompile == true) {
+ this->DebugTryCompileOn();
+ }
+ if (expandedPreset->DebugFind == true) {
+ this->SetDebugFindOutputOn(true);
+ }
+ }
+#endif
}
cmake::LogLevel cmake::StringToLogLevel(const std::string& levelStr)
@@ -1217,7 +1406,7 @@ createExtraGenerator(
}
std::unique_ptr<cmGlobalGenerator> cmake::CreateGlobalGenerator(
- const std::string& gname)
+ const std::string& gname, bool allowArch)
{
std::pair<std::unique_ptr<cmExternalMakefileProjectGenerator>, std::string>
extra = createExtraGenerator(this->ExtraGenerators, gname);
@@ -1227,7 +1416,7 @@ std::unique_ptr<cmGlobalGenerator> cmake::CreateGlobalGenerator(
std::unique_ptr<cmGlobalGenerator> generator;
for (const auto& g : this->Generators) {
- generator = g->CreateGlobalGenerator(name, this);
+ generator = g->CreateGlobalGenerator(name, allowArch, this);
if (generator) {
break;
}
@@ -1240,6 +1429,79 @@ std::unique_ptr<cmGlobalGenerator> cmake::CreateGlobalGenerator(
return generator;
}
+bool cmake::CreateAndSetGlobalGenerator(const std::string& name,
+ bool allowArch)
+{
+ auto gen = this->CreateGlobalGenerator(name, allowArch);
+ if (!gen) {
+ std::string kdevError;
+ std::string vsError;
+ if (name.find("KDevelop3", 0) != std::string::npos) {
+ kdevError = "\nThe KDevelop3 generator is not supported anymore.";
+ }
+ if (!allowArch && cmHasLiteralPrefix(name, "Visual Studio ") &&
+ name.length() >= cmStrLen("Visual Studio xx xxxx ")) {
+ vsError = "\nUsing platforms in Visual Studio generator names is not "
+ "supported in CMakePresets.json.";
+ }
+
+ cmSystemTools::Error(
+ cmStrCat("Could not create named generator ", name, kdevError, vsError));
+ this->PrintGeneratorList();
+ return false;
+ }
+
+ this->SetGlobalGenerator(std::move(gen));
+ return true;
+}
+
+#ifndef CMAKE_BOOTSTRAP
+void cmake::PrintPresetList(const cmCMakePresetsFile& file) const
+{
+ std::vector<GeneratorInfo> generators;
+ this->GetRegisteredGenerators(generators, false);
+
+ std::vector<cmCMakePresetsFile::UnexpandedPreset> presets;
+ for (auto const& p : file.PresetOrder) {
+ auto const& preset = file.Presets.at(p);
+ if (!preset.Hidden &&
+ std::find_if(generators.begin(), generators.end(),
+ [&preset](const GeneratorInfo& info) {
+ return info.name == preset.Generator;
+ }) != generators.end() &&
+ file.ExpandMacros(preset)) {
+ presets.push_back(preset);
+ }
+ }
+
+ if (presets.empty()) {
+ return;
+ }
+
+ std::cout << "Available presets:\n\n";
+
+ auto longestPresetName =
+ std::max_element(presets.begin(), presets.end(),
+ [](const cmCMakePresetsFile::UnexpandedPreset& a,
+ const cmCMakePresetsFile::UnexpandedPreset& b) {
+ return a.Name.length() < b.Name.length();
+ });
+ auto longestLength = longestPresetName->Name.length();
+
+ for (auto const& preset : presets) {
+ std::cout << " \"" << preset.Name << '"';
+ auto const& description = preset.DisplayName;
+ if (!description.empty()) {
+ for (std::size_t i = 0; i < longestLength - preset.Name.length(); ++i) {
+ std::cout << ' ';
+ }
+ std::cout << " - " << description;
+ }
+ std::cout << '\n';
+ }
+}
+#endif
+
void cmake::SetHomeDirectory(const std::string& dir)
{
this->State->SetSourceDirectory(dir);
@@ -1803,6 +2065,9 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
if (cmSystemTools::GetErrorOccuredFlag()) {
return -1;
}
+ if (this->GetWorkingMode() == HELP_MODE) {
+ return 0;
+ }
// Log the trace format version to the desired output
if (this->GetTrace()) {
@@ -1831,11 +2096,19 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
this->AddCMakePaths();
}
+#ifndef CMAKE_BOOTSTRAP
+ this->ProcessPresetVariables();
+ this->ProcessPresetEnvironment();
+#endif
// Add any cache args
if (!this->SetCacheArgs(args)) {
cmSystemTools::Error("Problem processing arguments. Aborting.\n");
return -1;
}
+#ifndef CMAKE_BOOTSTRAP
+ this->PrintPresetVariables();
+ this->PrintPresetEnvironment();
+#endif
// In script mode we terminate after running the script.
if (this->GetWorkingMode() != NORMAL_MODE) {
diff --git a/Source/cmake.h b/Source/cmake.h
index 63635cb..262d673 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -27,7 +27,11 @@
#include "cmStateTypes.h"
#if !defined(CMAKE_BOOTSTRAP)
+# include <cm/optional>
+
# include <cm3p/json/value.h>
+
+# include "cmCMakePresetsFile.h"
#endif
class cmExternalMakefileProjectGeneratorFactory;
@@ -88,13 +92,22 @@ public:
enum WorkingMode
{
NORMAL_MODE, ///< Cmake runs to create project files
- /** \brief Script mode (started by using -P).
- *
- * In script mode there is no generator and no cache. Also,
- * languages are not enabled, so add_executable and things do
- * nothing.
- */
+
+ /** \brief Script mode (started by using -P).
+ *
+ * In script mode there is no generator and no cache. Also,
+ * languages are not enabled, so add_executable and things do
+ * nothing.
+ */
SCRIPT_MODE,
+
+ /** \brief Help mode
+ *
+ * Used to print help for things that can only be determined after finding
+ * the source directory, for example, the list of presets.
+ */
+ HELP_MODE,
+
/** \brief A pkg-config like mode
*
* In this mode cmake just searches for a package and prints the results to
@@ -219,7 +232,15 @@ public:
//! Create a GlobalGenerator
std::unique_ptr<cmGlobalGenerator> CreateGlobalGenerator(
- const std::string& name);
+ const std::string& name, bool allowArch = true);
+
+ //! Create a GlobalGenerator and set it as our own
+ bool CreateAndSetGlobalGenerator(const std::string& name, bool allowArch);
+
+#ifndef CMAKE_BOOTSTRAP
+ //! Print list of presets
+ void PrintPresetList(const cmCMakePresetsFile& file) const;
+#endif
//! Return the global generator assigned to this instance of cmake
cmGlobalGenerator* GetGlobalGenerator()
@@ -329,9 +350,22 @@ public:
bool GetIsInTryCompile() const;
void SetIsInTryCompile(bool b);
+#ifndef CMAKE_BOOTSTRAP
+ void SetWarningFromPreset(const std::string& name,
+ const cm::optional<bool>& warning,
+ const cm::optional<bool>& error);
+ void ProcessPresetVariables();
+ void PrintPresetVariables();
+ void ProcessPresetEnvironment();
+ void PrintPresetEnvironment();
+#endif
+
//! Parse command line arguments that might set cache values
bool SetCacheArgs(const std::vector<std::string>&);
+ void ProcessCacheArg(const std::string& var, const std::string& value,
+ cmStateEnums::CacheEntryType type);
+
using ProgressCallbackType = std::function<void(const std::string&, float)>;
/**
* Set the function used by GUIs to receive progress updates
@@ -625,6 +659,12 @@ private:
std::unique_ptr<cmFileTimeCache> FileTimeCache;
std::string GraphVizFile;
InstalledFilesMap InstalledFiles;
+#ifndef CMAKE_BOOTSTRAP
+ std::map<std::string, cm::optional<cmCMakePresetsFile::CacheVariable>>
+ UnprocessedPresetVariables;
+ std::map<std::string, cm::optional<std::string>>
+ UnprocessedPresetEnvironment;
+#endif
#if !defined(CMAKE_BOOTSTRAP)
std::unique_ptr<cmVariableWatch> VariableWatch;
@@ -664,6 +704,8 @@ private:
#define CMAKE_STANDARD_OPTIONS_TABLE \
{ "-S <path-to-source>", "Explicitly specify a source directory." }, \
{ "-B <path-to-build>", "Explicitly specify a build directory." }, \
+ { "--preset=<preset-name>", "Explicitly specify a preset." }, \
+ { "--list-presets", "List available presets." }, \
{ "-C <initial-cache>", "Pre-load a script to populate the cache." }, \
{ "-D <var>[:<type>]=<value>", "Create or update a cmake cache entry." }, \
{ "-U <globbing_expr>", "Remove matching entries from CMake cache." }, \
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 4600fc5..c769227 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -49,7 +49,8 @@ const char* cmDocumentationUsage[][2] = {
{ nullptr,
" cmake [options] <path-to-source>\n"
" cmake [options] <path-to-existing-build>\n"
- " cmake [options] -S <path-to-source> -B <path-to-build>" },
+ " cmake [options] -S <path-to-source> -B <path-to-build>\n"
+ " cmake [options] -S <path-to-source> --preset=<preset-name>" },
{ nullptr,
"Specify a source directory to (re-)generate a build system for "
"it in the current working directory. Specify an existing build "
@@ -253,6 +254,9 @@ int do_cmake(int ac, char const* const* av)
} else if (cmHasLiteralPrefix(av[i], "--find-package")) {
workingMode = cmake::FIND_PACKAGE_MODE;
args.emplace_back(av[i]);
+ } else if (strcmp(av[i], "--list-presets") == 0) {
+ workingMode = cmake::HELP_MODE;
+ args.emplace_back(av[i]);
} else {
args.emplace_back(av[i]);
}
@@ -269,6 +273,7 @@ int do_cmake(int ac, char const* const* av)
cmState::Mode mode = cmState::Unknown;
switch (workingMode) {
case cmake::NORMAL_MODE:
+ case cmake::HELP_MODE:
mode = cmState::Project;
break;
case cmake::SCRIPT_MODE:
diff --git a/Tests/CMakeGUI/CMakeGUITest.cmake b/Tests/CMakeGUI/CMakeGUITest.cmake
index b60ec35..2c6baf3 100644
--- a/Tests/CMakeGUI/CMakeGUITest.cmake
+++ b/Tests/CMakeGUI/CMakeGUITest.cmake
@@ -27,6 +27,10 @@ function(run_cmake_gui_test name)
if(EXISTS "${_cmakelists_in}")
configure_file("${_cmakelists_in}" "${_workdir}/src/CMakeLists.txt" @ONLY)
endif()
+ set(_cmakepresets_in "${_srcdir}/CMakePresets.json.in")
+ if(EXISTS "${_cmakepresets_in}")
+ configure_file("${_cmakepresets_in}" "${_workdir}/src/CMakePresets.json" @ONLY)
+ endif()
if(_rcgt_DO_CONFIGURE)
if(NOT _rcgt_GENERATOR)
set(_rcgt_GENERATOR "${CMakeGUITest_GENERATOR}")
@@ -118,3 +122,37 @@ set(ENV{KEPT_VARIABLE} "Kept variable")
set(ENV{CHANGED_VARIABLE} "This variable will be changed")
set(ENV{REMOVED_VARIABLE} "Removed variable")
run_cmake_gui_test(environment)
+
+run_cmake_gui_test(presetArg:preset
+ ARGS
+ -S "${CMakeGUITest_BINARY_DIR}/presetArg-preset/src"
+ "--preset=ninja"
+ )
+run_cmake_gui_test(presetArg:presetBinary
+ ARGS
+ -S "${CMakeGUITest_BINARY_DIR}/presetArg-presetBinary/src"
+ -B "${CMakeGUITest_BINARY_DIR}/presetArg-presetBinary/build"
+ "--preset=ninja"
+ )
+run_cmake_gui_test(presetArg:presetBinaryChange
+ ARGS
+ -S "${CMakeGUITest_BINARY_DIR}/presetArg-presetBinaryChange/src"
+ -B "${CMakeGUITest_BINARY_DIR}/presetArg-presetBinaryChange/build"
+ "--preset=ninja"
+ )
+run_cmake_gui_test(presetArg:noPresetBinaryChange
+ ARGS
+ -S "${CMakeGUITest_BINARY_DIR}/presetArg-noPresetBinaryChange/src"
+ -B "${CMakeGUITest_BINARY_DIR}/presetArg-noPresetBinaryChange/build"
+ )
+run_cmake_gui_test(presetArg:presetConfigExists
+ ARGS
+ -S "${CMakeGUITest_BINARY_DIR}/presetArg-presetConfigExists/src"
+ "--preset=ninja"
+ )
+run_cmake_gui_test(presetArg:noExist
+ ARGS
+ -S "${CMakeGUITest_BINARY_DIR}/presetArg-noExist/src"
+ "--preset=noExist"
+ )
+run_cmake_gui_test(changingPresets)
diff --git a/Tests/CMakeGUI/CMakeGUITest.cxx b/Tests/CMakeGUI/CMakeGUITest.cxx
index 80ea08d..5a6bec3 100644
--- a/Tests/CMakeGUI/CMakeGUITest.cxx
+++ b/Tests/CMakeGUI/CMakeGUITest.cxx
@@ -5,6 +5,10 @@
#include "QCMake.h"
#include <QApplication>
#include <QEventLoop>
+#include <QFile>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
#include <QMessageBox>
#include <QSettings>
#include <QString>
@@ -18,8 +22,11 @@
#include "CatchShow.h"
#include "FirstConfigure.h"
+using WindowSetupHelper = std::function<void(CMakeSetupDialog*)>;
+Q_DECLARE_METATYPE(WindowSetupHelper)
+
namespace {
-void loopSleep(int msecs = 100)
+void loopSleep(int msecs = 500)
{
QEventLoop loop;
QTimer::singleShot(msecs, &loop, &QEventLoop::quit);
@@ -172,6 +179,264 @@ void CMakeGUITest::environment()
QCOMPARE(penv.value("REMOVED_VARIABLE"), "Removed variable");
}
+void CMakeGUITest::presetArg()
+{
+ QFETCH(WindowSetupHelper, setupFunction);
+ QFETCH(QString, presetName);
+ QFETCH(QString, sourceDir);
+ QFETCH(QString, binaryDir);
+ QFETCH(QCMakePropertyList, properties);
+
+ if (setupFunction) {
+ setupFunction(this->m_window);
+ }
+
+ // Wait a bit for everything to update
+ loopSleep();
+
+ QCOMPARE(this->m_window->Preset->presetName(), presetName);
+ QCOMPARE(this->m_window->SourceDirectory->text(), sourceDir);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(), binaryDir);
+
+ auto actualProperties =
+ this->m_window->CacheValues->cacheModel()->properties();
+ QCOMPARE(actualProperties.size(), properties.size());
+ for (int i = 0; i < actualProperties.size(); ++i) {
+ // operator==() only compares Key, we need to compare Value and Type too
+ QCOMPARE(actualProperties[i].Key, properties[i].Key);
+ QCOMPARE(actualProperties[i].Value, properties[i].Value);
+ QCOMPARE(actualProperties[i].Type, properties[i].Type);
+ }
+}
+
+namespace {
+QCMakePropertyList makePresetProperties(const QString& name)
+{
+ return QCMakePropertyList{
+ QCMakeProperty{
+ /*Key=*/"FALSE_VARIABLE",
+ /*Value=*/false,
+ /*Strings=*/{},
+ /*Help=*/"",
+ /*Type=*/QCMakeProperty::BOOL,
+ /*Advanced=*/false,
+ },
+ QCMakeProperty{
+ /*Key=*/"FILEPATH_VARIABLE",
+ /*Value=*/
+ QString::fromLocal8Bit(CMakeGUITest_BINARY_DIR "/%1/src/CMakeLists.txt")
+ .arg(name),
+ /*Strings=*/{},
+ /*Help=*/"",
+ /*Type=*/QCMakeProperty::FILEPATH,
+ /*Advanced=*/false,
+ },
+ QCMakeProperty{
+ /*Key=*/"ON_VARIABLE",
+ /*Value=*/true,
+ /*Strings=*/{},
+ /*Help=*/"",
+ /*Type=*/QCMakeProperty::BOOL,
+ /*Advanced=*/false,
+ },
+ QCMakeProperty{
+ /*Key=*/"PATH_VARIABLE",
+ /*Value=*/
+ QString::fromLocal8Bit(CMakeGUITest_BINARY_DIR "/%1/src").arg(name),
+ /*Strings=*/{},
+ /*Help=*/"",
+ /*Type=*/QCMakeProperty::PATH,
+ /*Advanced=*/false,
+ },
+ QCMakeProperty{
+ /*Key=*/"STRING_VARIABLE",
+ /*Value=*/"String value",
+ /*Strings=*/{},
+ /*Help=*/"",
+ /*Type=*/QCMakeProperty::STRING,
+ /*Advanced=*/false,
+ },
+ QCMakeProperty{
+ /*Key=*/"UNINITIALIZED_VARIABLE",
+ /*Value=*/"Uninitialized value",
+ /*Strings=*/{},
+ /*Help=*/"",
+ /*Type=*/QCMakeProperty::STRING,
+ /*Advanced=*/false,
+ },
+ };
+}
+}
+
+void CMakeGUITest::presetArg_data()
+{
+ QTest::addColumn<WindowSetupHelper>("setupFunction");
+ QTest::addColumn<QString>("presetName");
+ QTest::addColumn<QString>("sourceDir");
+ QTest::addColumn<QString>("binaryDir");
+ QTest::addColumn<QCMakePropertyList>("properties");
+
+ QTest::newRow("preset") << WindowSetupHelper{} << "ninja"
+ << CMakeGUITest_BINARY_DIR "/presetArg-preset/src"
+ << CMakeGUITest_BINARY_DIR
+ "/presetArg-preset/src/build"
+ << makePresetProperties("presetArg-preset");
+ QTest::newRow("presetBinary")
+ << WindowSetupHelper{} << "ninja"
+ << CMakeGUITest_BINARY_DIR "/presetArg-presetBinary/src"
+ << CMakeGUITest_BINARY_DIR "/presetArg-presetBinary/build"
+ << makePresetProperties("presetArg-presetBinary");
+ QTest::newRow("presetBinaryChange")
+ << WindowSetupHelper{ [](CMakeSetupDialog* window) {
+ loopSleep();
+ window->Preset->setPresetName("ninja2");
+ } }
+ << "ninja2" << CMakeGUITest_BINARY_DIR "/presetArg-presetBinaryChange/src"
+ << CMakeGUITest_BINARY_DIR "/presetArg-presetBinaryChange/src/build"
+ << makePresetProperties("presetArg-presetBinaryChange");
+ QTest::newRow("noPresetBinaryChange")
+ << WindowSetupHelper{ [](CMakeSetupDialog* window) {
+ loopSleep();
+ window->Preset->setPresetName("ninja");
+ } }
+ << "ninja" << CMakeGUITest_BINARY_DIR "/presetArg-noPresetBinaryChange/src"
+ << CMakeGUITest_BINARY_DIR "/presetArg-noPresetBinaryChange/src/build"
+ << makePresetProperties("presetArg-noPresetBinaryChange");
+ QTest::newRow("presetConfigExists")
+ << WindowSetupHelper{} << "ninja"
+ << CMakeGUITest_BINARY_DIR "/presetArg-presetConfigExists/src"
+ << CMakeGUITest_BINARY_DIR "/presetArg-presetConfigExists/src/build"
+ << makePresetProperties("presetArg-presetConfigExists");
+ QTest::newRow("noExist") << WindowSetupHelper{} << QString{}
+ << CMakeGUITest_BINARY_DIR "/presetArg-noExist/src"
+ << "" << QCMakePropertyList{};
+}
+
+namespace {
+void writePresets(const QString& buildDir, const QStringList& names)
+{
+ QJsonArray presets{
+ QJsonObject{
+ { "name", "base" },
+ { "generator", "Ninja" },
+ { "binaryDir",
+ QString::fromLocal8Bit("${sourceDir}/%1/${presetName}")
+ .arg(buildDir) },
+ { "hidden", true },
+ },
+ };
+
+ for (auto const& name : names) {
+ presets.append(QJsonObject{
+ { "name", name },
+ { "inherits", QJsonArray{ "base" } },
+ });
+ }
+
+ QJsonDocument doc{ QJsonObject{
+ { "version", 1 },
+ { "configurePresets", presets },
+ } };
+
+ QFile presetsFile(CMakeGUITest_BINARY_DIR
+ "/changingPresets/src/CMakePresets.json");
+ bool open = presetsFile.open(QIODevice::WriteOnly);
+ Q_ASSERT(open);
+ presetsFile.write(doc.toJson());
+}
+}
+
+void CMakeGUITest::changingPresets()
+{
+ QDir::root().mkpath(CMakeGUITest_BINARY_DIR "/changingPresets/src");
+
+ this->m_window->SourceDirectory->setText(CMakeGUITest_BINARY_DIR
+ "/changingPresets/src");
+ loopSleep();
+ QCOMPARE(this->m_window->Preset->presetName(), QString{});
+ QCOMPARE(this->m_window->Preset->presets().size(), 0);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(), "");
+ QCOMPARE(this->m_window->Preset->isHidden(), true);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), true);
+
+ writePresets("build1", { "preset" });
+ loopSleep(1500);
+ QCOMPARE(this->m_window->Preset->presetName(), QString{});
+ QCOMPARE(this->m_window->Preset->presets().size(), 1);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(), "");
+ QCOMPARE(this->m_window->Preset->isHidden(), false);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), false);
+
+ this->m_window->Preset->setPresetName("preset");
+ loopSleep();
+ QCOMPARE(this->m_window->Preset->presetName(), "preset");
+ QCOMPARE(this->m_window->Preset->presets().size(), 1);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(),
+ CMakeGUITest_BINARY_DIR "/changingPresets/src/build1/preset");
+ QCOMPARE(this->m_window->Preset->isHidden(), false);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), false);
+
+ writePresets("build2", { "preset2", "preset" });
+ loopSleep(1500);
+ QCOMPARE(this->m_window->Preset->presetName(), "preset");
+ QCOMPARE(this->m_window->Preset->presets().size(), 2);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(),
+ CMakeGUITest_BINARY_DIR "/changingPresets/src/build1/preset");
+ QCOMPARE(this->m_window->Preset->isHidden(), false);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), false);
+
+ writePresets("build3", { "preset2" });
+ loopSleep(1500);
+ QCOMPARE(this->m_window->Preset->presetName(), QString{});
+ QCOMPARE(this->m_window->Preset->presets().size(), 1);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(),
+ CMakeGUITest_BINARY_DIR "/changingPresets/src/build1/preset");
+ QCOMPARE(this->m_window->Preset->isHidden(), false);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), false);
+
+ this->m_window->Preset->setPresetName("preset2");
+ loopSleep();
+ QCOMPARE(this->m_window->Preset->presetName(), "preset2");
+ QCOMPARE(this->m_window->Preset->presets().size(), 1);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(),
+ CMakeGUITest_BINARY_DIR "/changingPresets/src/build3/preset2");
+ QCOMPARE(this->m_window->Preset->isHidden(), false);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), false);
+
+ QDir::root().mkpath(CMakeGUITest_BINARY_DIR "/changingPresets/src2");
+ QFile::copy(CMakeGUITest_BINARY_DIR "/changingPresets/src/CMakePresets.json",
+ CMakeGUITest_BINARY_DIR
+ "/changingPresets/src2/CMakePresets.json");
+ this->m_window->SourceDirectory->setText(CMakeGUITest_BINARY_DIR
+ "/changingPresets/src2");
+ loopSleep();
+ QCOMPARE(this->m_window->Preset->presetName(), QString{});
+ QCOMPARE(this->m_window->Preset->presets().size(), 1);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(),
+ CMakeGUITest_BINARY_DIR "/changingPresets/src/build3/preset2");
+ QCOMPARE(this->m_window->Preset->isHidden(), false);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), false);
+
+ this->m_window->Preset->setPresetName("preset2");
+ loopSleep();
+ QCOMPARE(this->m_window->Preset->presetName(), "preset2");
+ QCOMPARE(this->m_window->Preset->presets().size(), 1);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(),
+ CMakeGUITest_BINARY_DIR "/changingPresets/src2/build3/preset2");
+ QCOMPARE(this->m_window->Preset->isHidden(), false);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), false);
+
+ QFile(CMakeGUITest_BINARY_DIR "/changingPresets/src2/CMakePresets.json")
+ .remove();
+ loopSleep(1500);
+ QCOMPARE(this->m_window->Preset->presetName(), QString{});
+ QCOMPARE(this->m_window->Preset->presets().size(), 0);
+ QCOMPARE(this->m_window->BinaryDirectory->currentText(),
+ CMakeGUITest_BINARY_DIR "/changingPresets/src2/build3/preset2");
+ QCOMPARE(this->m_window->Preset->isHidden(), true);
+ QCOMPARE(this->m_window->PresetLabel->isHidden(), true);
+}
+
void SetupDefaultQSettings()
{
QSettings::setDefaultFormat(QSettings::IniFormat);
diff --git a/Tests/CMakeGUI/CMakeGUITest.h b/Tests/CMakeGUI/CMakeGUITest.h
index 891cf62..e6293a4 100644
--- a/Tests/CMakeGUI/CMakeGUITest.h
+++ b/Tests/CMakeGUI/CMakeGUITest.h
@@ -23,4 +23,7 @@ private slots:
void simpleConfigure();
void simpleConfigure_data();
void environment();
+ void presetArg();
+ void presetArg_data();
+ void changingPresets();
};
diff --git a/Tests/CMakeGUI/CMakeLists.txt b/Tests/CMakeGUI/CMakeLists.txt
index c6bc88a..4e8609b 100644
--- a/Tests/CMakeGUI/CMakeLists.txt
+++ b/Tests/CMakeGUI/CMakeLists.txt
@@ -72,3 +72,24 @@ add_cmake_gui_lib_test(QCMakeCacheModel
MOC_SOURCES
QCMakeCacheModelTest.h
)
+add_cmake_gui_lib_test(QCMakePreset
+ SOURCES
+ QCMakePresetTest.cxx
+ QCMakePresetTest.h
+ MOC_SOURCES
+ QCMakePresetTest.h
+ )
+add_cmake_gui_lib_test(QCMakePresetItemModel
+ SOURCES
+ QCMakePresetItemModelTest.cxx
+ QCMakePresetItemModelTest.h
+ MOC_SOURCES
+ QCMakePresetItemModelTest.h
+ )
+add_cmake_gui_lib_test(QCMakePresetComboBox
+ SOURCES
+ QCMakePresetComboBoxTest.cxx
+ QCMakePresetComboBoxTest.h
+ MOC_SOURCES
+ QCMakePresetComboBoxTest.h
+ )
diff --git a/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx b/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx
new file mode 100644
index 0000000..6ee55c3
--- /dev/null
+++ b/Tests/CMakeGUI/QCMakePresetComboBoxTest.cxx
@@ -0,0 +1,80 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMakePresetComboBoxTest.h"
+
+#include <QtTest>
+
+void QCMakePresetComboBoxTest::changePresets()
+{
+ QCMakePresetComboBox box;
+ QSignalSpy presetChanged(&box, &QCMakePresetComboBox::presetChanged);
+
+ QCOMPARE(presetChanged.size(), 0);
+
+ box.setPresets({});
+ QCOMPARE(presetChanged.size(), 0);
+
+ box.setPresetName(QString{});
+ QCOMPARE(presetChanged.size(), 0);
+
+ box.setPresets({
+ {
+ /*name=*/"preset",
+ /*description=*/"",
+ /*description=*/"",
+ /*generator=*/"Ninja",
+ /*architecture=*/"",
+ /*toolset=*/"",
+ /*setGenConfig=*/true,
+ /*enabled=*/true,
+ },
+ });
+ QCOMPARE(presetChanged.size(), 0);
+
+ box.setPresetName(QString{});
+ QCOMPARE(presetChanged.size(), 0);
+
+ box.setPresetName("noexist");
+ QCOMPARE(presetChanged.size(), 0);
+
+ box.setPresetName("preset");
+ QCOMPARE(presetChanged.size(), 1);
+ QCOMPARE(presetChanged.last(), QList<QVariant>{ "preset" });
+
+ box.setPresets({
+ {
+ /*name=*/"preset",
+ /*description=*/"",
+ /*description=*/"",
+ /*generator=*/"Ninja Multi-Config",
+ /*architecture=*/"",
+ /*toolset=*/"",
+ /*setGenConfig=*/true,
+ /*enabled=*/true,
+ },
+ });
+ QCOMPARE(presetChanged.size(), 1);
+
+ box.setPresetName("noexist");
+ QCOMPARE(presetChanged.size(), 2);
+ QCOMPARE(presetChanged.last(), QList<QVariant>{ QString{} });
+
+ box.setPresetName("preset");
+ QCOMPARE(presetChanged.size(), 3);
+ QCOMPARE(presetChanged.last(), QList<QVariant>{ "preset" });
+
+ box.blockSignals(true);
+ box.setPresetName(QString{});
+ box.blockSignals(false);
+ QCOMPARE(presetChanged.size(), 3);
+
+ box.setPresetName("preset");
+ QCOMPARE(presetChanged.size(), 4);
+ QCOMPARE(presetChanged.last(), QList<QVariant>{ "preset" });
+
+ box.setPresets({});
+ QCOMPARE(presetChanged.size(), 5);
+ QCOMPARE(presetChanged.last(), QList<QVariant>{ QString{} });
+}
+
+QTEST_MAIN(QCMakePresetComboBoxTest)
diff --git a/Tests/CMakeGUI/QCMakePresetComboBoxTest.h b/Tests/CMakeGUI/QCMakePresetComboBoxTest.h
new file mode 100644
index 0000000..433adbb
--- /dev/null
+++ b/Tests/CMakeGUI/QCMakePresetComboBoxTest.h
@@ -0,0 +1,13 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "QCMakePresetComboBox.h"
+#include <QObject>
+
+class QCMakePresetComboBoxTest : public QObject
+{
+ Q_OBJECT
+private slots:
+ void changePresets();
+};
diff --git a/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx b/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx
new file mode 100644
index 0000000..ee45d39
--- /dev/null
+++ b/Tests/CMakeGUI/QCMakePresetItemModelTest.cxx
@@ -0,0 +1,162 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMakePresetItemModelTest.h"
+
+#include <utility>
+
+#include "QCMakePreset.h"
+#include "QCMakePresetItemModel.h"
+#include <QHash>
+#include <QMetaType>
+#include <QSignalSpy>
+#include <QVariant>
+#include <QVector>
+#include <QtTest>
+
+using QItemDataHash = QHash<Qt::ItemDataRole, QVariant>;
+
+void QCMakePresetItemModelTest::initTestCase()
+{
+ QMetaType::registerComparators<QCMakePreset>();
+}
+
+void QCMakePresetItemModelTest::initTestCase_data()
+{
+ QTest::addColumn<QVector<QCMakePreset>>("presets");
+ QTest::addColumn<QVector<QItemDataHash>>("data");
+
+ QVector<QCMakePreset> presets{
+ QCMakePreset{
+ /*name=*/"no-description",
+ /*description=*/"",
+ /*description=*/"",
+ /*generator=*/"",
+ /*architecture=*/"",
+ /*toolset=*/"",
+ /*setGenConfig=*/true,
+ /*enabled=*/true,
+ },
+ QCMakePreset{
+ /*name=*/"short-description",
+ /*description=*/"Short Description",
+ /*description=*/"",
+ /*generator=*/"",
+ /*architecture=*/"",
+ /*toolset=*/"",
+ /*setGenConfig=*/true,
+ /*enabled=*/true,
+ },
+ QCMakePreset{
+ /*name=*/"long-description",
+ /*description=*/"",
+ /*description=*/"Long Description",
+ /*generator=*/"",
+ /*architecture=*/"",
+ /*toolset=*/"",
+ /*setGenConfig=*/true,
+ /*enabled=*/true,
+ },
+ QCMakePreset{
+ /*name=*/"disabled",
+ /*description=*/"",
+ /*description=*/"",
+ /*generator=*/"",
+ /*architecture=*/"",
+ /*toolset=*/"",
+ /*setGenConfig=*/true,
+ /*enabled=*/false,
+ },
+ };
+ QVector<QItemDataHash> data{
+ QItemDataHash{
+ { Qt::AccessibleDescriptionRole, "" },
+ { Qt::DisplayRole, "no-description" },
+ { Qt::ToolTipRole, "" },
+ { Qt::UserRole, QVariant::fromValue(presets[0]) },
+ { Qt::FontRole, QFont{} },
+ },
+ QItemDataHash{
+ { Qt::AccessibleDescriptionRole, "" },
+ { Qt::DisplayRole, "Short Description" },
+ { Qt::ToolTipRole, "" },
+ { Qt::UserRole, QVariant::fromValue(presets[1]) },
+ { Qt::FontRole, QFont{} },
+ },
+ QItemDataHash{
+ { Qt::AccessibleDescriptionRole, "" },
+ { Qt::DisplayRole, "long-description" },
+ { Qt::ToolTipRole, "Long Description" },
+ { Qt::UserRole, QVariant::fromValue(presets[2]) },
+ { Qt::FontRole, QFont{} },
+ },
+ QItemDataHash{
+ { Qt::AccessibleDescriptionRole, "" },
+ { Qt::DisplayRole, "disabled" },
+ { Qt::ToolTipRole, "" },
+ { Qt::UserRole, QVariant::fromValue(presets[3]) },
+ { Qt::FontRole, QFont{} },
+ },
+ QItemDataHash{
+ { Qt::AccessibleDescriptionRole, "separator" },
+ { Qt::DisplayRole, QVariant{} },
+ { Qt::ToolTipRole, QVariant{} },
+ { Qt::UserRole, QVariant{} },
+ { Qt::FontRole, QFont{} },
+ },
+ QItemDataHash{
+ { Qt::AccessibleDescriptionRole, "" },
+ { Qt::DisplayRole, "<custom>" },
+ { Qt::ToolTipRole, "Specify all settings manually" },
+ { Qt::UserRole, QVariant{} },
+ { Qt::FontRole,
+ []() {
+ QFont f;
+ f.setItalic(true);
+ return f;
+ }() },
+ },
+ };
+ QTest::newRow("many") << presets << data;
+ QTest::newRow("none") << QVector<QCMakePreset>{}
+ << QVector<QItemDataHash>{ data.last() };
+}
+
+void QCMakePresetItemModelTest::data()
+{
+ QFETCH_GLOBAL(QVector<QCMakePreset>, presets);
+ QFETCH_GLOBAL(QVector<QItemDataHash>, data);
+ QFETCH(Qt::ItemDataRole, role);
+
+ QCMakePresetItemModel model;
+ QSignalSpy spy1(&model, &QCMakePresetItemModel::modelAboutToBeReset);
+ QSignalSpy spy2(&model, &QCMakePresetItemModel::modelReset);
+ model.setPresets(presets);
+ QCOMPARE(spy1.size(), 1);
+ QCOMPARE(spy2.size(), 1);
+
+ QVector<QVariant> expectedData(data.size());
+ for (int i = 0; i < data.size(); ++i) {
+ expectedData[i] = data[i][role];
+ }
+
+ auto rows = model.rowCount();
+ QVector<QVariant> actualData(rows);
+ for (int i = 0; i < rows; ++i) {
+ actualData[i] = model.data(model.index(i, 0), role);
+ }
+
+ QCOMPARE(actualData, expectedData);
+}
+
+void QCMakePresetItemModelTest::data_data()
+{
+ QTest::addColumn<Qt::ItemDataRole>("role");
+
+ QTest::newRow("accessible") << Qt::AccessibleDescriptionRole;
+ QTest::newRow("display") << Qt::DisplayRole;
+ QTest::newRow("tooltip") << Qt::ToolTipRole;
+ QTest::newRow("user") << Qt::UserRole;
+ QTest::newRow("font") << Qt::FontRole;
+}
+
+QTEST_MAIN(QCMakePresetItemModelTest)
diff --git a/Tests/CMakeGUI/QCMakePresetItemModelTest.h b/Tests/CMakeGUI/QCMakePresetItemModelTest.h
new file mode 100644
index 0000000..ff6efae
--- /dev/null
+++ b/Tests/CMakeGUI/QCMakePresetItemModelTest.h
@@ -0,0 +1,17 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "QCMakePresetItemModel.h"
+#include <QObject>
+
+class QCMakePresetItemModelTest : public QObject
+{
+ Q_OBJECT
+private slots:
+ void initTestCase();
+ void initTestCase_data();
+
+ void data();
+ void data_data();
+};
diff --git a/Tests/CMakeGUI/QCMakePresetTest.cxx b/Tests/CMakeGUI/QCMakePresetTest.cxx
new file mode 100644
index 0000000..8fd07e7
--- /dev/null
+++ b/Tests/CMakeGUI/QCMakePresetTest.cxx
@@ -0,0 +1,82 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "QCMakePresetTest.h"
+
+#include <utility>
+
+#include "QCMakePreset.h"
+#include <QtTest>
+
+namespace {
+QCMakePreset makePreset()
+{
+ return QCMakePreset{
+ /*name=*/"name",
+ /*displayName=*/"displayName",
+ /*description=*/"description",
+ /*generator=*/"generator",
+ /*architecture=*/"architecture",
+ /*toolset=*/"toolset",
+ /*setGenConfig=*/true,
+ /*enabled=*/true,
+ };
+}
+
+template <typename T, typename U>
+QCMakePreset makePreset(T QCMakePreset::*field, U&& value)
+{
+ auto preset = makePreset();
+ preset.*field = std::forward<U>(value);
+ return preset;
+}
+}
+
+void QCMakePresetTest::equality()
+{
+ QFETCH(QCMakePreset, rhs);
+ QFETCH(bool, equal);
+ QFETCH(bool, lt);
+ QFETCH(bool, gt);
+
+ auto lhs = makePreset();
+ QVERIFY((lhs == rhs) == equal);
+ QVERIFY((lhs != rhs) == !equal);
+ QVERIFY((lhs < rhs) == lt);
+ QVERIFY((lhs >= rhs) == !lt);
+ QVERIFY((lhs > rhs) == gt);
+ QVERIFY((lhs <= rhs) == !gt);
+}
+
+void QCMakePresetTest::equality_data()
+{
+ QTest::addColumn<QCMakePreset>("rhs");
+ QTest::addColumn<bool>("equal");
+ QTest::addColumn<bool>("lt");
+ QTest::addColumn<bool>("gt");
+
+ QTest::newRow("equal") << makePreset() << true << false << false;
+ QTest::newRow("name") << makePreset(&QCMakePreset::name, "other-name")
+ << false << true << false;
+ QTest::newRow("displayName")
+ << makePreset(&QCMakePreset::displayName, "other-displayName") << false
+ << true << false;
+ QTest::newRow("description")
+ << makePreset(&QCMakePreset::description, "other-description") << false
+ << true << false;
+ QTest::newRow("generator")
+ << makePreset(&QCMakePreset::generator, "other-generator") << false << true
+ << false;
+ QTest::newRow("architecture")
+ << makePreset(&QCMakePreset::architecture, "other-architecture") << false
+ << true << false;
+ QTest::newRow("toolset") << makePreset(&QCMakePreset::toolset,
+ "other-toolset")
+ << false << false << true;
+ QTest::newRow("setGenConfig")
+ << makePreset(&QCMakePreset::setGenConfig, false) << false << false
+ << true;
+ QTest::newRow("enabled") << makePreset(&QCMakePreset::enabled, false)
+ << false << false << true;
+}
+
+QTEST_MAIN(QCMakePresetTest)
diff --git a/Tests/CMakeGUI/QCMakePresetTest.h b/Tests/CMakeGUI/QCMakePresetTest.h
new file mode 100644
index 0000000..5eac88d
--- /dev/null
+++ b/Tests/CMakeGUI/QCMakePresetTest.h
@@ -0,0 +1,14 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include "QCMakePreset.h"
+#include <QObject>
+
+class QCMakePresetTest : public QObject
+{
+ Q_OBJECT
+private slots:
+ void equality();
+ void equality_data();
+};
diff --git a/Tests/CMakeGUI/presetArg-noPresetBinaryChange/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-noPresetBinaryChange/CMakePresets.json.in
new file mode 100644
index 0000000..d78d69d
--- /dev/null
+++ b/Tests/CMakeGUI/presetArg-noPresetBinaryChange/CMakePresets.json.in
@@ -0,0 +1,33 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ninja",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "STRING_VARIABLE": {
+ "type": "STRING",
+ "value": "String value"
+ },
+ "PATH_VARIABLE": {
+ "type": "PATH",
+ "value": "${sourceDir}"
+ },
+ "FILEPATH_VARIABLE": {
+ "type": "FILEPATH",
+ "value": "${sourceDir}/CMakeLists.txt"
+ },
+ "ON_VARIABLE": {
+ "type": "BOOL",
+ "value": "ON"
+ },
+ "FALSE_VARIABLE": {
+ "type": "BOOL",
+ "value": "FALSE"
+ },
+ "UNINITIALIZED_VARIABLE": "Uninitialized value"
+ }
+ }
+ ]
+}
diff --git a/Tests/CMakeGUI/presetArg-preset/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-preset/CMakePresets.json.in
new file mode 100644
index 0000000..d78d69d
--- /dev/null
+++ b/Tests/CMakeGUI/presetArg-preset/CMakePresets.json.in
@@ -0,0 +1,33 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ninja",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "STRING_VARIABLE": {
+ "type": "STRING",
+ "value": "String value"
+ },
+ "PATH_VARIABLE": {
+ "type": "PATH",
+ "value": "${sourceDir}"
+ },
+ "FILEPATH_VARIABLE": {
+ "type": "FILEPATH",
+ "value": "${sourceDir}/CMakeLists.txt"
+ },
+ "ON_VARIABLE": {
+ "type": "BOOL",
+ "value": "ON"
+ },
+ "FALSE_VARIABLE": {
+ "type": "BOOL",
+ "value": "FALSE"
+ },
+ "UNINITIALIZED_VARIABLE": "Uninitialized value"
+ }
+ }
+ ]
+}
diff --git a/Tests/CMakeGUI/presetArg-presetBinary/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-presetBinary/CMakePresets.json.in
new file mode 100644
index 0000000..d78d69d
--- /dev/null
+++ b/Tests/CMakeGUI/presetArg-presetBinary/CMakePresets.json.in
@@ -0,0 +1,33 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ninja",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "STRING_VARIABLE": {
+ "type": "STRING",
+ "value": "String value"
+ },
+ "PATH_VARIABLE": {
+ "type": "PATH",
+ "value": "${sourceDir}"
+ },
+ "FILEPATH_VARIABLE": {
+ "type": "FILEPATH",
+ "value": "${sourceDir}/CMakeLists.txt"
+ },
+ "ON_VARIABLE": {
+ "type": "BOOL",
+ "value": "ON"
+ },
+ "FALSE_VARIABLE": {
+ "type": "BOOL",
+ "value": "FALSE"
+ },
+ "UNINITIALIZED_VARIABLE": "Uninitialized value"
+ }
+ }
+ ]
+}
diff --git a/Tests/CMakeGUI/presetArg-presetBinaryChange/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-presetBinaryChange/CMakePresets.json.in
new file mode 100644
index 0000000..6fe20d6
--- /dev/null
+++ b/Tests/CMakeGUI/presetArg-presetBinaryChange/CMakePresets.json.in
@@ -0,0 +1,39 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ninja",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "STRING_VARIABLE": {
+ "type": "STRING",
+ "value": "String value"
+ },
+ "PATH_VARIABLE": {
+ "type": "PATH",
+ "value": "${sourceDir}"
+ },
+ "FILEPATH_VARIABLE": {
+ "type": "FILEPATH",
+ "value": "${sourceDir}/CMakeLists.txt"
+ },
+ "ON_VARIABLE": {
+ "type": "BOOL",
+ "value": "ON"
+ },
+ "FALSE_VARIABLE": {
+ "type": "BOOL",
+ "value": "FALSE"
+ },
+ "UNINITIALIZED_VARIABLE": "Uninitialized value"
+ }
+ },
+ {
+ "name": "ninja2",
+ "inherits": [
+ "ninja"
+ ]
+ }
+ ]
+}
diff --git a/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeLists.txt.in b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeLists.txt.in
new file mode 100644
index 0000000..2ae4a57
--- /dev/null
+++ b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeLists.txt.in
@@ -0,0 +1,2 @@
+cmake_minimum_required(VERSION 3.18)
+project(sourceBinaryArgs-sourceDir NONE)
diff --git a/Tests/CMakeGUI/presetArg-presetConfigExists/CMakePresets.json.in b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakePresets.json.in
new file mode 100644
index 0000000..d78d69d
--- /dev/null
+++ b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakePresets.json.in
@@ -0,0 +1,33 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ninja",
+ "generator": "Ninja",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "STRING_VARIABLE": {
+ "type": "STRING",
+ "value": "String value"
+ },
+ "PATH_VARIABLE": {
+ "type": "PATH",
+ "value": "${sourceDir}"
+ },
+ "FILEPATH_VARIABLE": {
+ "type": "FILEPATH",
+ "value": "${sourceDir}/CMakeLists.txt"
+ },
+ "ON_VARIABLE": {
+ "type": "BOOL",
+ "value": "ON"
+ },
+ "FALSE_VARIABLE": {
+ "type": "BOOL",
+ "value": "FALSE"
+ },
+ "UNINITIALIZED_VARIABLE": "Uninitialized value"
+ }
+ }
+ ]
+}
diff --git a/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeSetup.ini.in b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeSetup.ini.in
new file mode 100644
index 0000000..a5d0c71
--- /dev/null
+++ b/Tests/CMakeGUI/presetArg-presetConfigExists/CMakeSetup.ini.in
@@ -0,0 +1,2 @@
+[Settings]
+StartPath\WhereBuild0=@CMake_BINARY_DIR@
diff --git a/Tests/CMakeLib/testJSONHelpers.cxx b/Tests/CMakeLib/testJSONHelpers.cxx
index 78eed5b..a45d320 100644
--- a/Tests/CMakeLib/testJSONHelpers.cxx
+++ b/Tests/CMakeLib/testJSONHelpers.cxx
@@ -37,6 +37,7 @@ enum class ErrorCode
InvalidInt,
InvalidBool,
InvalidString,
+ InvalidSubObject,
InvalidObject,
InvalidArray,
MissingRequired,
@@ -148,15 +149,20 @@ bool testString()
bool testObject()
{
+ auto const subhelper =
+ cmJSONObjectHelper<ObjectStruct, ErrorCode>(ErrorCode::Success,
+ ErrorCode::InvalidSubObject)
+ .Bind("subfield"_s, &ObjectStruct::Field2, IntHelper);
auto const helper = cmJSONObjectHelper<ObjectStruct, ErrorCode>(
ErrorCode::Success, ErrorCode::InvalidObject)
.Bind("field1"_s, &ObjectStruct::Field1, StringHelper)
- .Bind("field2"_s, &ObjectStruct::Field2, IntHelper)
+ .Bind("field2"_s, subhelper)
.Bind<std::string>("field3"_s, nullptr, StringHelper);
Json::Value v(Json::objectValue);
v["field1"] = "Hello";
- v["field2"] = 2;
+ v["field2"] = Json::objectValue;
+ v["field2"]["subfield"] = 2;
v["field3"] = "world!";
v["extra"] = "extra";
@@ -165,29 +171,34 @@ bool testObject()
ASSERT_TRUE(s1.Field1 == "Hello");
ASSERT_TRUE(s1.Field2 == 2);
- v["field2"] = "wrong";
+ v["field2"]["subfield"] = "wrong";
ObjectStruct s2;
ASSERT_TRUE(helper(s2, &v) == ErrorCode::InvalidInt);
- v.removeMember("field2");
+ v["field2"].removeMember("subfield");
ObjectStruct s3;
- ASSERT_TRUE(helper(s3, &v) == ErrorCode::InvalidObject);
+ ASSERT_TRUE(helper(s3, &v) == ErrorCode::InvalidSubObject);
- v["field2"] = 2;
- v["field3"] = 3;
+ v.removeMember("field2");
ObjectStruct s4;
- ASSERT_TRUE(helper(s4, &v) == ErrorCode::InvalidString);
+ ASSERT_TRUE(helper(s4, &v) == ErrorCode::InvalidObject);
- v.removeMember("field3");
+ v["field2"] = Json::objectValue;
+ v["field2"]["subfield"] = 2;
+ v["field3"] = 3;
ObjectStruct s5;
- ASSERT_TRUE(helper(s5, &v) == ErrorCode::InvalidObject);
+ ASSERT_TRUE(helper(s5, &v) == ErrorCode::InvalidString);
- v = "Hello";
+ v.removeMember("field3");
ObjectStruct s6;
ASSERT_TRUE(helper(s6, &v) == ErrorCode::InvalidObject);
+ v = "Hello";
ObjectStruct s7;
- ASSERT_TRUE(helper(s7, nullptr) == ErrorCode::InvalidObject);
+ ASSERT_TRUE(helper(s7, &v) == ErrorCode::InvalidObject);
+
+ ObjectStruct s8;
+ ASSERT_TRUE(helper(s8, nullptr) == ErrorCode::InvalidObject);
return true;
}
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 9d5c8fb..cd8cbc1 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -758,6 +758,7 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
-DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION})
add_RunCMake_test("UnityBuild")
+add_RunCMake_test(CMakePresets)
if(WIN32)
add_RunCMake_test(Win32GenEx)
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-stderr.txt b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-stderr.txt
new file mode 100644
index 0000000..a3b79b6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigDefault-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Error at CMakeLists\.txt:[0-9]+ \(project\):
+ Generator
+
+ [^
+]*
+
+ does not support platform specification, but platform
+
+ a
+
+ was specified\.$
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigIgnore.cmake
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-stderr.txt b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-stderr.txt
new file mode 100644
index 0000000..a3b79b6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CMakeGeneratorConfigNone-stderr.txt
@@ -0,0 +1,11 @@
+^CMake Error at CMakeLists\.txt:[0-9]+ \(project\):
+ Generator
+
+ [^
+]*
+
+ does not support platform specification, but platform
+
+ a
+
+ was specified\.$
diff --git a/Tests/RunCMake/CMakePresets/CMakeLists.txt.in b/Tests/RunCMake/CMakePresets/CMakeLists.txt.in
new file mode 100644
index 0000000..67c2d48
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CMakeLists.txt.in
@@ -0,0 +1,4 @@
+cmake_minimum_required(VERSION 3.18)
+project(${RunCMake_TEST} NONE)
+set(RunCMake_SOURCE_DIR [==[@RunCMake_SOURCE_DIR@]==])
+include("${RunCMake_SOURCE_DIR}/${RunCMake_TEST}.cmake")
diff --git a/Tests/RunCMake/CMakePresets/CMakePresets.json.in b/Tests/RunCMake/CMakePresets/CMakePresets.json.in
new file mode 100644
index 0000000..78e31c6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CMakePresets.json.in
@@ -0,0 +1,481 @@
+/*
+ * Block comment
+ */
+{
+ // Inline comment
+ "version": 1,
+ "cmakeMinimumRequired": {
+ "major": 3,
+ "minor": 18,
+ "patch": 0
+ },
+ "vendor": {
+ "example.com/ExampleIDE/1.0": true
+ },
+ "configurePresets": [
+ {
+ "name": "Good",
+ "displayName": "Good Preset",
+ "description": "This preset is meant to test most of the fields when set correctly.",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cmakeExecutable": "/path/does/not/exist/cmake",
+ "vendor": {
+ "example.com/ExampleIDE/1.0": {
+ "transmogrify": true
+ }
+ },
+ "cacheVariables": {
+ "TEST_SOURCE_DIR": {
+ "type": "PATH",
+ "value": "${sourceDir}"
+ },
+ "TEST_SOURCE_PARENT_DIR": {
+ "type": "PATH",
+ "value": "${sourceParentDir}"
+ },
+ "TEST_SOURCE_LIST": {
+ "type": "FILEPATH",
+ "value": "${sourceDir}/CMakeLists.txt"
+ },
+ "TEST_TRUE": {
+ "type": "BOOL",
+ "value": "TRUE"
+ },
+ "TEST_OFF": {
+ "type": "BOOL",
+ "value": "OFF"
+ },
+ "TEST_PRESET_NAME": {
+ "type": "STRING",
+ "value": "x${presetName}x"
+ },
+ "TEST_GENERATOR": {
+ "value": "x${generator}x"
+ },
+ "TEST_DOLLAR": {
+ "value": "${dollar}"
+ },
+ "TEST_ENV_REF": "$env{TEST_ENV_REF}",
+ "TEST_ENV": "$env{TEST_ENV}",
+ "TEST_D_ENV_REF": "$env{TEST_D_ENV_REF}",
+ "TEST_ENV_OVERRIDE": "$env{TEST_ENV_OVERRIDE}",
+ "TEST_PENV": "$env{TEST_PENV}",
+ "TEST_ENV_REF_PENV": "$env{TEST_ENV_REF_PENV}",
+ "TEST_ENV_REF_P": "$penv{TEST_ENV_REF}",
+ "TEST_ENV_P": "$penv{TEST_ENV}",
+ "TEST_D_ENV_REF_P": "$penv{TEST_D_ENV_REF}",
+ "TEST_ENV_OVERRIDE_P": "$penv{TEST_ENV_OVERRIDE}",
+ "TEST_PENV_P": "$penv{TEST_PENV}",
+ "TEST_ENV_REF_PENV_P": "$penv{TEST_ENV_REF_PENV}",
+ "TEST_MULTIPLE_MACROS": "${presetName} ${generator}",
+ "TEST_EXPANSION": "\\${presetName} ${dollar}{dollar} $unknown{namespace} $en{NOT_ENV} $enve{NOT_ENV} $ \\$ $a",
+ "TEST_TRAILING_DOLLAR": "a $",
+ "TEST_TRAILING_BACKSLASH": "a \\",
+ "TEST_TRAILING_UNKNOWN_NAMESPACE": "$unknown{namespace",
+ "TEST_OVERRIDE_1": {
+ "type": "STRING",
+ "value": "Default value"
+ },
+ "TEST_OVERRIDE_2": "Default value",
+ "TEST_OVERRIDE_3": {
+ "type": "STRING",
+ "value": "Default value"
+ },
+ "TEST_OVERRIDE_4": {
+ "type": "STRING",
+ "value": "Default value"
+ },
+ "TEST_UNDEF": "undef"
+ },
+ "environment": {
+ "TEST_ENV_REF": "$env{TEST_ENV}",
+ "TEST_ENV": "Environment variable",
+ "TEST_D_ENV_REF": "x$env{TEST_ENV_REF}x",
+ "TEST_ENV_OVERRIDE": "Overridden environment variable",
+ "TEST_ENV_REF_PENV": "prefix+$penv{TEST_ENV_REF_PENV}",
+ "TEST_PENV": null
+ }
+ },
+ {
+ "name": "GoodNoArgs",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "GoodBinaryUp",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/../GoodBinaryUp-build"
+ },
+ {
+ "name": "GoodBinaryRelative",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "build"
+ },
+ {
+ "name": "Good Spaces",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "GoodWindowsBackslash",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}\\build"
+ },
+ {
+ "name": "GoodBinaryCmdLine",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "GoodGeneratorCmdLine",
+ "generator": "Invalid Generator",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "InvalidGeneratorCmdLine",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "GoodNoS",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "GoodInheritanceParentBase",
+ "hidden": true,
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "TEST_VARIABLE": {
+ "type": "STRING",
+ "value": "Some string"
+ }
+ },
+ "environment": {
+ "TEST_ENV": "Some environment variable"
+ }
+ },
+ {
+ "name": "GoodInheritanceParent",
+ "inherits": "GoodInheritanceParentBase"
+ },
+ {
+ "name": "GoodInheritanceChildBase",
+ "hidden": true
+ },
+ {
+ "name": "GoodInheritanceChild",
+ "inherits": "GoodInheritanceChildBase",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "TEST_VARIABLE": {
+ "type": "STRING",
+ "value": "Some string"
+ }
+ },
+ "environment": {
+ "TEST_ENV": "Some environment variable"
+ }
+ },
+ {
+ "name": "GoodInheritanceOverrideBase",
+ "hidden": true,
+ "generator": "Invalid Generator",
+ "binaryDir": "${sourceDir}/../GoodInheritanceBase-build",
+ "cacheVariables": {
+ "PARENT_VARIABLE": {
+ "type": "STRING",
+ "value": "Parent variable"
+ },
+ "OVERRIDDEN_VARIABLE": {
+ "type": "BOOL",
+ "value": "ON"
+ },
+ "DELETED_VARIABLE": "This variable will be deleted"
+ },
+ "environment": {
+ "PARENT_ENV": "Parent environment variable",
+ "OVERRIDDEN_ENV": "This environment variable will be overridden",
+ "DELETED_ENV": "This environment variable will be deleted"
+ }
+ },
+ {
+ "name": "GoodInheritanceOverride",
+ "inherits": "GoodInheritanceOverrideBase",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "OVERRIDDEN_VARIABLE": {
+ "type": "STRING",
+ "value": "Overridden variable"
+ },
+ "CHILD_VARIABLE": {
+ "type": "STRING",
+ "value": "Child variable"
+ },
+ "DELETED_VARIABLE": null
+ },
+ "environment": {
+ "OVERRIDDEN_ENV": "Overridden environment variable",
+ "CHILD_ENV": "Child environment variable",
+ "DELETED_ENV": null
+ }
+ },
+ {
+ "name": "GoodInheritanceOverrideDummy",
+ "inherits": "GoodInheritanceOverride"
+ },
+ {
+ "name": "GoodInheritanceMulti1",
+ "hidden": true,
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "FIRST_VARIABLE": {
+ "type": "STRING",
+ "value": "First variable"
+ },
+ "OVERRIDDEN_VARIABLE": {
+ "type": "STRING",
+ "value": "Overridden variable"
+ }
+ },
+ "environment": {
+ "FIRST_ENV": "First environment variable",
+ "OVERRIDDEN_ENV": "Overridden environment variable"
+ }
+ },
+ {
+ "name": "GoodInheritanceMulti2",
+ "hidden": true,
+ "generator": "Invalid Generator",
+ "binaryDir": "${sourceDir}/../GoodInheritanceMulti2-build",
+ "cacheVariables": {
+ "SECOND_VARIABLE": {
+ "type": "STRING",
+ "value": "Second variable"
+ },
+ "OVERRIDDEN_VARIABLE": {
+ "type": "BOOL",
+ "value": "ON"
+ }
+ },
+ "environment": {
+ "SECOND_ENV": "Second environment variable",
+ "OVERRIDDEN_ENV": "This will be overridden"
+ }
+ },
+ {
+ "name": "GoodInheritanceMulti",
+ "inherits": [
+ "GoodInheritanceMulti1",
+ "GoodInheritanceMulti2"
+ ]
+ },
+ {
+ "name": "GoodInheritanceMultiSecond1",
+ "hidden": true
+ },
+ {
+ "name": "GoodInheritanceMultiSecond2",
+ "hidden": true,
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "GoodInheritanceMultiSecond",
+ "inherits": [
+ "GoodInheritanceMultiSecond1",
+ "GoodInheritanceMultiSecond2"
+ ]
+ },
+ {
+ "name": "GoodInheritanceMacroBase",
+ "hidden": true,
+ "cacheVariables": {
+ "PRESET_NAME": "${presetName}"
+ }
+ },
+ {
+ "name": "GoodInheritanceMacro",
+ "inherits": "GoodInheritanceMacroBase",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "UnclosedMacro",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir"
+ },
+ {
+ "name": "NoSuchMacro",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${noexist}"
+ },
+ {
+ "name": "VendorMacro",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "$vendor{unknown.unknownMacro}"
+ },
+ {
+ "name": "InvalidGenerator",
+ "generator": "Invalid Generator",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "EnvCycle",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "environment": {
+ "ENV_1": "$env{ENV_2}",
+ "ENV_2": "$env{ENV_1}"
+ }
+ },
+ {
+ "name": "UseHiddenPreset",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "hidden": true
+ },
+ {
+ "name": "VisualStudioGeneratorArch",
+ "generator": "@RunCMake_GENERATOR@ Win64",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "VisualStudioWin32",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "architecture": "Win32"
+ },
+ {
+ "name": "VisualStudioWin64",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "architecture": "x64"
+ },
+ {
+ "name": "VisualStudioWin32Override",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "architecture": "Win32"
+ },
+ {
+ "name": "VisualStudioToolset",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "toolset": "Test Toolset"
+ },
+ {
+ "name": "VisualStudioToolsetOverride",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "toolset": "Invalid Toolset"
+ },
+ {
+ "name": "VisualStudioInheritanceParentBase",
+ "hidden": true,
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "architecture": "Test Platform",
+ "toolset": "Test Toolset"
+ },
+ {
+ "name": "VisualStudioInheritanceParent",
+ "inherits": "VisualStudioInheritanceParentBase"
+ },
+ {
+ "name": "VisualStudioInheritanceChildBase",
+ "hidden": true
+ },
+ {
+ "name": "VisualStudioInheritanceChild",
+ "inherits": "VisualStudioInheritanceChildBase",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "architecture": "Test Platform",
+ "toolset": "Test Toolset"
+ },
+ {
+ "name": "VisualStudioInheritanceOverrideBase",
+ "hidden": true,
+ "architecture": "Invalid Platform",
+ "toolset": "Invalid Toolset"
+ },
+ {
+ "name": "VisualStudioInheritanceOverride",
+ "inherits": "VisualStudioInheritanceOverrideBase",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "architecture": "Test Platform",
+ "toolset": "Test Toolset"
+ },
+ {
+ "name": "VisualStudioInheritanceMulti1",
+ "hidden": true,
+ "architecture": "Test Platform",
+ "toolset": "Test Toolset"
+ },
+ {
+ "name": "VisualStudioInheritanceMulti2",
+ "hidden": true,
+ "architecture": "Invalid Platform",
+ "toolset": "Invalid Toolset"
+ },
+ {
+ "name": "VisualStudioInheritanceMulti",
+ "inherits": [
+ "VisualStudioInheritanceMulti1",
+ "VisualStudioInheritanceMulti2"
+ ],
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "VisualStudioInheritanceMultiSecond1",
+ "hidden": true
+ },
+ {
+ "name": "VisualStudioInheritanceMultiSecond2",
+ "hidden": true,
+ "architecture": "Test Platform",
+ "toolset": "Test Toolset"
+ },
+ {
+ "name": "VisualStudioInheritanceMultiSecond",
+ "inherits": [
+ "VisualStudioInheritanceMultiSecond1",
+ "VisualStudioInheritanceMultiSecond2"
+ ],
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "CMakeGeneratorConfigNone",
+ "generator": "@RunCMake_GENERATOR@",
+ "architecture": "a",
+ "toolset": "a",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "CMakeGeneratorConfigBase",
+ "generator": "@RunCMake_GENERATOR@",
+ "architecture": "a",
+ "toolset": "a",
+ "cmakeGeneratorConfig": "ignore",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "CMakeGeneratorConfigDefault",
+ "inherits": "CMakeGeneratorConfigBase",
+ "cmakeGeneratorConfig": "default"
+ },
+ {
+ "name": "CMakeGeneratorConfigIgnore",
+ "inherits": "CMakeGeneratorConfigBase"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/CacheOverride.cmake b/Tests/RunCMake/CMakePresets/CacheOverride.cmake
new file mode 100644
index 0000000..d0ebe17
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CacheOverride.cmake
@@ -0,0 +1,2 @@
+set(TEST_OVERRIDE_3 "Overridden value" CACHE STRING "")
+set(TEST_OVERRIDE_4 "Overridden value" CACHE INTERNAL "")
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance0-result.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance0-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance0-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt
new file mode 100644
index 0000000..895afcb
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance0-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/CyclicInheritance0: Cyclic preset inheritance$
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance0.json.in b/Tests/RunCMake/CMakePresets/CyclicInheritance0.json.in
new file mode 100644
index 0000000..3468936
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance0.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "CyclicInheritance0",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "inherits": [
+ "CyclicInheritance0"
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance1-result.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt
new file mode 100644
index 0000000..1e59e92
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance1-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/CyclicInheritance1: Cyclic preset inheritance$
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance1.json.in b/Tests/RunCMake/CMakePresets/CyclicInheritance1.json.in
new file mode 100644
index 0000000..fabd4af
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance1.json.in
@@ -0,0 +1,21 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "CyclicInheritance0",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "inherits": [
+ "CyclicInheritance1"
+ ]
+ },
+ {
+ "name": "CyclicInheritance1",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "inherits": [
+ "CyclicInheritance0"
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance2-result.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt b/Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt
new file mode 100644
index 0000000..56e630b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance2-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/CyclicInheritance2: Cyclic preset inheritance$
diff --git a/Tests/RunCMake/CMakePresets/CyclicInheritance2.json.in b/Tests/RunCMake/CMakePresets/CyclicInheritance2.json.in
new file mode 100644
index 0000000..0e1d7d4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/CyclicInheritance2.json.in
@@ -0,0 +1,29 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "CyclicInheritance0",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "inherits": [
+ "CyclicInheritance1"
+ ]
+ },
+ {
+ "name": "CyclicInheritance1",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "inherits": [
+ "CyclicInheritance2"
+ ]
+ },
+ {
+ "name": "CyclicInheritance2",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "inherits": [
+ "CyclicInheritance0"
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/Debug-stderr.txt b/Tests/RunCMake/CMakePresets/Debug-stderr.txt
new file mode 100644
index 0000000..7fdb8b3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Debug-stderr.txt
@@ -0,0 +1 @@
+ find_package considered the following locations for the Config module:
diff --git a/Tests/RunCMake/CMakePresets/Debug-stdout.txt b/Tests/RunCMake/CMakePresets/Debug-stdout.txt
new file mode 100644
index 0000000..7d1f388
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Debug-stdout.txt
@@ -0,0 +1,4 @@
+-- Generating [^
+]*/Tests/RunCMake/CMakePresets/Debug/build
+ Called from: \[1\][^
+]*/Tests/RunCMake/CMakePresets/Debug/CMakeLists\.txt
diff --git a/Tests/RunCMake/CMakePresets/Debug.cmake b/Tests/RunCMake/CMakePresets/Debug.cmake
new file mode 100644
index 0000000..19c7db2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Debug.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/DebugBase.cmake)
+if(NOT EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/CMakeLists.txt")
+ message(SEND_ERROR "Debugging try_compile() did not work")
+endif()
diff --git a/Tests/RunCMake/CMakePresets/Debug.json.in b/Tests/RunCMake/CMakePresets/Debug.json.in
new file mode 100644
index 0000000..500700e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Debug.json.in
@@ -0,0 +1,19 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "NoDebug",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "Debug",
+ "inherits": "NoDebug",
+ "debug": {
+ "output": true,
+ "find": true,
+ "tryCompile": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/DebugBase.cmake b/Tests/RunCMake/CMakePresets/DebugBase.cmake
new file mode 100644
index 0000000..870f31c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/DebugBase.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+try_compile(_result ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/main.c)
+find_package(ThisPackageHopefullyDoesNotExist CONFIG)
diff --git a/Tests/RunCMake/CMakePresets/DisableWarningFlags.cmake b/Tests/RunCMake/CMakePresets/DisableWarningFlags.cmake
new file mode 100644
index 0000000..5de7687
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/DisableWarningFlags.cmake
@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/WarningsBase.cmake)
diff --git a/Tests/RunCMake/CMakePresets/DuplicatePresets-result.txt b/Tests/RunCMake/CMakePresets/DuplicatePresets-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/DuplicatePresets-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt b/Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt
new file mode 100644
index 0000000..c9361ae
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/DuplicatePresets-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/DuplicatePresets: Duplicate presets$
diff --git a/Tests/RunCMake/CMakePresets/DuplicatePresets.json.in b/Tests/RunCMake/CMakePresets/DuplicatePresets.json.in
new file mode 100644
index 0000000..cf388e7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/DuplicatePresets.json.in
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "DuplicatePresets",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "DuplicatePresets",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/EmptyPresetName-result.txt b/Tests/RunCMake/CMakePresets/EmptyPresetName-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/EmptyPresetName-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt b/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt
new file mode 100644
index 0000000..6970674
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/EmptyPresetName-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/EmptyPresetName: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/EmptyPresetName.json.in b/Tests/RunCMake/CMakePresets/EmptyPresetName.json.in
new file mode 100644
index 0000000..fd4bedd
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/EmptyPresetName.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/EnvCycle-result.txt b/Tests/RunCMake/CMakePresets/EnvCycle-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/EnvCycle-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt b/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt
new file mode 100644
index 0000000..c8568f1
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/EnvCycle-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: Could not evaluate preset "EnvCycle": Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/ErrorDeprecated-result.txt b/Tests/RunCMake/CMakePresets/ErrorDeprecated-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorDeprecated-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ErrorDeprecated-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorDeprecated-stderr.txt
new file mode 100644
index 0000000..964a504
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorDeprecated-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Deprecation Error at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+ Deprecation warning
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakePresets/ErrorDeprecated\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/CMakePresets/ErrorDeprecated.cmake b/Tests/RunCMake/CMakePresets/ErrorDeprecated.cmake
new file mode 100644
index 0000000..5de7687
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorDeprecated.cmake
@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/WarningsBase.cmake)
diff --git a/Tests/RunCMake/CMakePresets/ErrorDev-result.txt b/Tests/RunCMake/CMakePresets/ErrorDev-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorDev-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt
new file mode 100644
index 0000000..f76478c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorDev-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Error \(dev\) at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+ Dev warning
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakePresets/ErrorDev\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This error is for project developers\. Use -Wno-error=dev to suppress it\.$
diff --git a/Tests/RunCMake/CMakePresets/ErrorDev.cmake b/Tests/RunCMake/CMakePresets/ErrorDev.cmake
new file mode 100644
index 0000000..5de7687
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorDev.cmake
@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/WarningsBase.cmake)
diff --git a/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-result.txt b/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt
new file mode 100644
index 0000000..3221345
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated.json.in b/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated.json.in
new file mode 100644
index 0000000..664b3ee
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorNoWarningDeprecated.json.in
@@ -0,0 +1,16 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ErrorNoWarningDeprecated",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "warnings": {
+ "deprecated": false
+ },
+ "errors": {
+ "deprecated": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-result.txt b/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt b/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt
new file mode 100644
index 0000000..d2ddb90
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorNoWarningDev-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ErrorNoWarningDev: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/ErrorNoWarningDev.json.in b/Tests/RunCMake/CMakePresets/ErrorNoWarningDev.json.in
new file mode 100644
index 0000000..d681b2a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ErrorNoWarningDev.json.in
@@ -0,0 +1,16 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ErrorNoWarningDev",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "warnings": {
+ "dev": false
+ },
+ "errors": {
+ "dev": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/ExtraPresetField-result.txt b/Tests/RunCMake/CMakePresets/ExtraPresetField-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraPresetField-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt b/Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt
new file mode 100644
index 0000000..559e3c2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraPresetField-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ExtraPresetField: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/ExtraPresetField.json.in b/Tests/RunCMake/CMakePresets/ExtraPresetField.json.in
new file mode 100644
index 0000000..b529758
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraPresetField.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ExtraPresetField",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "invalid": true
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/ExtraRootField-result.txt b/Tests/RunCMake/CMakePresets/ExtraRootField-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraRootField-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt b/Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt
new file mode 100644
index 0000000..bb281be
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraRootField-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ExtraRootField: Invalid root object$
diff --git a/Tests/RunCMake/CMakePresets/ExtraRootField.json.in b/Tests/RunCMake/CMakePresets/ExtraRootField.json.in
new file mode 100644
index 0000000..bcfa68b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraRootField.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ExtraRootField",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ],
+ "invalid": true
+}
diff --git a/Tests/RunCMake/CMakePresets/ExtraVariableField-result.txt b/Tests/RunCMake/CMakePresets/ExtraVariableField-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraVariableField-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt b/Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt
new file mode 100644
index 0000000..9b346e7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraVariableField-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/ExtraVariableField: Invalid CMake variable definition$
diff --git a/Tests/RunCMake/CMakePresets/ExtraVariableField.json.in b/Tests/RunCMake/CMakePresets/ExtraVariableField.json.in
new file mode 100644
index 0000000..a810560
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ExtraVariableField.json.in
@@ -0,0 +1,16 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "ExtraVariableField",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "EXTRA": {
+ "value": "",
+ "invalid": true
+ }
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/Good-stdout.txt b/Tests/RunCMake/CMakePresets/Good-stdout.txt
new file mode 100644
index 0000000..ce6189e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Good-stdout.txt
@@ -0,0 +1,46 @@
+Preset CMake variables:
+
+ TEST_DOLLAR="\$"
+ TEST_D_ENV_REF="xEnvironment variablex"
+ TEST_D_ENV_REF_P=""
+ TEST_ENV="Environment variable"
+ TEST_ENV_OVERRIDE="Overridden environment variable"
+ TEST_ENV_OVERRIDE_P="This environment variable will be overridden"
+ TEST_ENV_P=""
+ TEST_ENV_REF="Environment variable"
+ TEST_ENV_REF_P=""
+ TEST_ENV_REF_PENV="prefix\+suffix"
+ TEST_ENV_REF_PENV_P="suffix"
+ TEST_EXPANSION="\\Good \${dollar} \$unknown{namespace} \$en{NOT_ENV} \$enve{NOT_ENV} \$ \\\$ \$a"
+ TEST_GENERATOR="x[^
+]*x"
+ TEST_MULTIPLE_MACROS="Good [^
+]*"
+ TEST_OFF:BOOL="OFF"
+ TEST_OVERRIDE_3:STRING="Default value"
+ TEST_OVERRIDE_4:STRING="Default value"
+ TEST_PENV="Process environment variable"
+ TEST_PENV_P="Process environment variable"
+ TEST_PRESET_NAME:STRING="xGoodx"
+ TEST_SOURCE_DIR:PATH="[^
+]*/Tests/RunCMake/CMakePresets/Good"
+ TEST_SOURCE_LIST:FILEPATH="[^
+]*/Tests/RunCMake/CMakePresets/Good/CMakeLists\.txt"
+ TEST_SOURCE_PARENT_DIR:PATH="[^
+]*/Tests/RunCMake/CMakePresets"
+ TEST_TRAILING_BACKSLASH="a \\"
+ TEST_TRAILING_DOLLAR="a \$"
+ TEST_TRAILING_UNKNOWN_NAMESPACE="\$unknown{namespace"
+ TEST_TRUE:BOOL="TRUE"
+
+Preset environment variables:
+
+ TEST_D_ENV_REF="xEnvironment variablex"
+ TEST_ENV="Environment variable"
+ TEST_ENV_OVERRIDE="Overridden environment variable"
+ TEST_ENV_REF="Environment variable"
+ TEST_ENV_REF_PENV="prefix\+suffix"
+
+(-- Selecting Windows SDK version [^
+]*
+)?-- Configuring done
diff --git a/Tests/RunCMake/CMakePresets/Good.cmake b/Tests/RunCMake/CMakePresets/Good.cmake
new file mode 100644
index 0000000..d8e3e2d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Good.cmake
@@ -0,0 +1,45 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent_dir "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(CMAKE_GENERATOR "" "${RunCMake_GENERATOR}")
+test_variable(TEST_SOURCE_DIR "PATH" "${CMAKE_SOURCE_DIR}")
+test_variable(TEST_SOURCE_PARENT_DIR "PATH" "${_parent_dir}")
+test_variable(TEST_SOURCE_LIST "FILEPATH" "${CMAKE_SOURCE_DIR}/CMakeLists.txt")
+test_variable(TEST_TRUE "BOOL" "TRUE")
+test_variable(TEST_OFF "BOOL" "OFF")
+test_variable(TEST_PRESET_NAME "STRING" "xGoodx")
+test_variable(TEST_GENERATOR "UNINITIALIZED" "x${CMAKE_GENERATOR}x")
+test_variable(TEST_DOLLAR "UNINITIALIZED" "$")
+test_variable(TEST_ENV_REF "UNINITIALIZED" "Environment variable")
+test_variable(TEST_ENV "UNINITIALIZED" "Environment variable")
+test_variable(TEST_D_ENV_REF "UNINITIALIZED" "xEnvironment variablex")
+test_variable(TEST_ENV_OVERRIDE "UNINITIALIZED" "Overridden environment variable")
+test_variable(TEST_PENV "UNINITIALIZED" "Process environment variable")
+test_variable(TEST_ENV_REF_PENV "UNINITIALIZED" "prefix+suffix")
+test_variable(TEST_ENV_REF_P "UNINITIALIZED" "")
+test_variable(TEST_ENV_P "UNINITIALIZED" "")
+test_variable(TEST_D_ENV_REF_P "UNINITIALIZED" "")
+test_variable(TEST_ENV_OVERRIDE_P "UNINITIALIZED" "This environment variable will be overridden")
+test_variable(TEST_PENV_P "UNINITIALIZED" "Process environment variable")
+test_variable(TEST_ENV_REF_PENV_P "UNINITIALIZED" "suffix")
+test_variable(TEST_MULTIPLE_MACROS "UNINITIALIZED" "Good ${CMAKE_GENERATOR}")
+test_variable(TEST_EXPANSION "UNINITIALIZED" "\\Good \${dollar} \$unknown{namespace} \$en{NOT_ENV} \$enve{NOT_ENV} $ \\$ $a")
+test_variable(TEST_TRAILING_DOLLAR "UNINITIALIZED" "a $")
+test_variable(TEST_TRAILING_BACKSLASH "UNINITIALIZED" "a \\")
+test_variable(TEST_TRAILING_UNKNOWN_NAMESPACE "UNINITIALIZED" "\$unknown{namespace")
+test_variable(TEST_OVERRIDE_1 "UNINITIALIZED" "Overridden value")
+test_variable(TEST_OVERRIDE_2 "STRING" "Overridden value")
+test_variable(TEST_OVERRIDE_3 "STRING" "Default value")
+test_variable(TEST_OVERRIDE_4 "INTERNAL" "Overridden value")
+
+if(DEFINED TEST_UNDEF OR DEFINED CACHE{TEST_UNDEF})
+ message(SEND_ERROR "TEST_UNDEF should not be defined")
+endif()
+
+test_environment_variable(TEST_ENV_REF "Environment variable")
+test_environment_variable(TEST_ENV "Environment variable")
+test_environment_variable(TEST_D_ENV_REF "xEnvironment variablex")
+test_environment_variable(TEST_ENV_OVERRIDE "Overridden environment variable")
+test_environment_variable(TEST_PENV "Process environment variable")
+test_environment_variable(TEST_ENV_REF_PENV "prefix+suffix")
diff --git a/Tests/RunCMake/CMakePresets/GoodBOM.cmake b/Tests/RunCMake/CMakePresets/GoodBOM.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodBOM.cmake
diff --git a/Tests/RunCMake/CMakePresets/GoodBOM.json.in b/Tests/RunCMake/CMakePresets/GoodBOM.json.in
new file mode 100644
index 0000000..2152511
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodBOM.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "GoodBOM",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodBinaryCmdLine.cmake b/Tests/RunCMake/CMakePresets/GoodBinaryCmdLine.cmake
new file mode 100644
index 0000000..9f928fe
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodBinaryCmdLine.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${_parent}/GoodBinaryCmdLine-build")
diff --git a/Tests/RunCMake/CMakePresets/GoodBinaryRelative.cmake b/Tests/RunCMake/CMakePresets/GoodBinaryRelative.cmake
new file mode 100644
index 0000000..49e7a25
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodBinaryRelative.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
diff --git a/Tests/RunCMake/CMakePresets/GoodBinaryUp.cmake b/Tests/RunCMake/CMakePresets/GoodBinaryUp.cmake
new file mode 100644
index 0000000..f7fb224
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodBinaryUp.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${_parent}/GoodBinaryUp-build")
diff --git a/Tests/RunCMake/CMakePresets/GoodGeneratorCmdLine.cmake b/Tests/RunCMake/CMakePresets/GoodGeneratorCmdLine.cmake
new file mode 100644
index 0000000..4319e72
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodGeneratorCmdLine.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_GENERATOR "" "${RunCMake_GENERATOR}")
diff --git a/Tests/RunCMake/CMakePresets/GoodInheritanceChild.cmake b/Tests/RunCMake/CMakePresets/GoodInheritanceChild.cmake
new file mode 100644
index 0000000..cfc93be
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInheritanceChild.cmake
@@ -0,0 +1,6 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(TEST_VARIABLE "STRING" "Some string")
+
+test_environment_variable(TEST_ENV "Some environment variable")
diff --git a/Tests/RunCMake/CMakePresets/GoodInheritanceMacro.cmake b/Tests/RunCMake/CMakePresets/GoodInheritanceMacro.cmake
new file mode 100644
index 0000000..96fede0
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInheritanceMacro.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(PRESET_NAME "UNINITIALIZED" "GoodInheritanceMacro")
diff --git a/Tests/RunCMake/CMakePresets/GoodInheritanceMulti.cmake b/Tests/RunCMake/CMakePresets/GoodInheritanceMulti.cmake
new file mode 100644
index 0000000..6430f4d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInheritanceMulti.cmake
@@ -0,0 +1,10 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(FIRST_VARIABLE "STRING" "First variable")
+test_variable(SECOND_VARIABLE "STRING" "Second variable")
+test_variable(OVERRIDDEN_VARIABLE "STRING" "Overridden variable")
+
+test_environment_variable(FIRST_ENV "First environment variable")
+test_environment_variable(SECOND_ENV "Second environment variable")
+test_environment_variable(OVERRIDDEN_ENV "Overridden environment variable")
diff --git a/Tests/RunCMake/CMakePresets/GoodInheritanceMultiSecond.cmake b/Tests/RunCMake/CMakePresets/GoodInheritanceMultiSecond.cmake
new file mode 100644
index 0000000..49e7a25
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInheritanceMultiSecond.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
diff --git a/Tests/RunCMake/CMakePresets/GoodInheritanceOverride.cmake b/Tests/RunCMake/CMakePresets/GoodInheritanceOverride.cmake
new file mode 100644
index 0000000..5231803
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInheritanceOverride.cmake
@@ -0,0 +1,18 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(PARENT_VARIABLE "STRING" "Parent variable")
+test_variable(OVERRIDDEN_VARIABLE "STRING" "Overridden variable")
+test_variable(CHILD_VARIABLE "STRING" "Child variable")
+
+if(DEFINED DELETED_VARIABLE OR DEFINED CACHE{DELETED_VARIABLE})
+ message(SEND_ERROR "DELETED_VARIABLE should not be defined")
+endif()
+
+test_environment_variable(PARENT_ENV "Parent environment variable")
+test_environment_variable(CHILD_ENV "Child environment variable")
+test_environment_variable(OVERRIDDEN_ENV "Overridden environment variable")
+
+if(DEFINED ENV{DELETED_ENV})
+ message(SEND_ERROR "DELETED_ENV should not be defined")
+endif()
diff --git a/Tests/RunCMake/CMakePresets/GoodInheritanceParent.cmake b/Tests/RunCMake/CMakePresets/GoodInheritanceParent.cmake
new file mode 100644
index 0000000..cfc93be
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodInheritanceParent.cmake
@@ -0,0 +1,6 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_BINARY_DIR "" "${CMAKE_SOURCE_DIR}/build")
+test_variable(TEST_VARIABLE "STRING" "Some string")
+
+test_environment_variable(TEST_ENV "Some environment variable")
diff --git a/Tests/RunCMake/CMakePresets/GoodNoArgs.cmake b/Tests/RunCMake/CMakePresets/GoodNoArgs.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodNoArgs.cmake
diff --git a/Tests/RunCMake/CMakePresets/GoodNoS.cmake b/Tests/RunCMake/CMakePresets/GoodNoS.cmake
new file mode 100644
index 0000000..1d3b2ff
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodNoS.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${_parent}/GoodNoS-build")
diff --git a/Tests/RunCMake/CMakePresets/GoodSpaces.cmake b/Tests/RunCMake/CMakePresets/GoodSpaces.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodSpaces.cmake
diff --git a/Tests/RunCMake/CMakePresets/GoodUserFromMain.cmake b/Tests/RunCMake/CMakePresets/GoodUserFromMain.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodUserFromMain.cmake
diff --git a/Tests/RunCMake/CMakePresets/GoodUserFromMain.json.in b/Tests/RunCMake/CMakePresets/GoodUserFromMain.json.in
new file mode 100644
index 0000000..348443e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodUserFromMain.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "GoodUserFromMain",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodUserFromMainUser.json.in b/Tests/RunCMake/CMakePresets/GoodUserFromMainUser.json.in
new file mode 100644
index 0000000..77b4ef6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodUserFromMainUser.json.in
@@ -0,0 +1,4 @@
+{
+ "version": 1,
+ "configurePresets": []
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodUserFromUser.cmake b/Tests/RunCMake/CMakePresets/GoodUserFromUser.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodUserFromUser.cmake
diff --git a/Tests/RunCMake/CMakePresets/GoodUserFromUser.json.in b/Tests/RunCMake/CMakePresets/GoodUserFromUser.json.in
new file mode 100644
index 0000000..77b4ef6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodUserFromUser.json.in
@@ -0,0 +1,4 @@
+{
+ "version": 1,
+ "configurePresets": []
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodUserFromUserUser.json.in b/Tests/RunCMake/CMakePresets/GoodUserFromUserUser.json.in
new file mode 100644
index 0000000..83196be
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodUserFromUserUser.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "GoodUserFromUser",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodUserOnly.cmake b/Tests/RunCMake/CMakePresets/GoodUserOnly.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodUserOnly.cmake
diff --git a/Tests/RunCMake/CMakePresets/GoodUserOnlyUser.json.in b/Tests/RunCMake/CMakePresets/GoodUserOnlyUser.json.in
new file mode 100644
index 0000000..274f4c7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodUserOnlyUser.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "GoodUserOnly",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/GoodWindowsBackslash.cmake b/Tests/RunCMake/CMakePresets/GoodWindowsBackslash.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/GoodWindowsBackslash.cmake
diff --git a/Tests/RunCMake/CMakePresets/HighVersion-result.txt b/Tests/RunCMake/CMakePresets/HighVersion-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/HighVersion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt b/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
new file mode 100644
index 0000000..d8622f2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/HighVersion-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/HighVersion: Unrecognized "version" field$
diff --git a/Tests/RunCMake/CMakePresets/HighVersion.json.in b/Tests/RunCMake/CMakePresets/HighVersion.json.in
new file mode 100644
index 0000000..8107842
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/HighVersion.json.in
@@ -0,0 +1,4 @@
+{
+ "version": 1000,
+ "configurePresets": []
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-result.txt b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt
new file mode 100644
index 0000000..72a20d5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
new file mode 100644
index 0000000..1479c66
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidCMakeGeneratorConfig.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "InvalidCMakeGeneratorConfig",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cmakeGeneratorConfig": {}
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidGenerator-result.txt b/Tests/RunCMake/CMakePresets/InvalidGenerator-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidGenerator-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidGenerator-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidGenerator-stderr.txt
new file mode 100644
index 0000000..c7dd19b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidGenerator-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not create named generator Invalid Generator
+
+Generators
diff --git a/Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-result.txt b/Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-stderr.txt
new file mode 100644
index 0000000..c7dd19b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidGeneratorCmdLine-stderr.txt
@@ -0,0 +1,3 @@
+^CMake Error: Could not create named generator Invalid Generator
+
+Generators
diff --git a/Tests/RunCMake/CMakePresets/InvalidInheritance-result.txt b/Tests/RunCMake/CMakePresets/InvalidInheritance-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidInheritance-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt
new file mode 100644
index 0000000..97f3876
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidInheritance-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidInheritance: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidInheritance.json.in b/Tests/RunCMake/CMakePresets/InvalidInheritance.json.in
new file mode 100644
index 0000000..77bd9a3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidInheritance.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "InvalidInheritance",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "inherits": [
+ "NoExist"
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-result.txt b/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt
new file mode 100644
index 0000000..2fe8c66
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir.json.in b/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir.json.in
new file mode 100644
index 0000000..2bb95d9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetBinaryDir.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "InvalidPresetBinaryDir",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": []
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-result.txt b/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-stderr.txt
new file mode 100644
index 0000000..9572875
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetGenerator-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidPresetGenerator: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetGenerator.json.in b/Tests/RunCMake/CMakePresets/InvalidPresetGenerator.json.in
new file mode 100644
index 0000000..95e6e65
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetGenerator.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "InvalidPresetGenerator",
+ "generator": [],
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetName-result.txt b/Tests/RunCMake/CMakePresets/InvalidPresetName-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetName-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetName-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresetName-stderr.txt
new file mode 100644
index 0000000..8f6ff7c
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetName-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidPresetName: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetName.json.in b/Tests/RunCMake/CMakePresets/InvalidPresetName.json.in
new file mode 100644
index 0000000..08361da
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetName.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": [],
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetVendor-result.txt b/Tests/RunCMake/CMakePresets/InvalidPresetVendor-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetVendor-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetVendor-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresetVendor-stderr.txt
new file mode 100644
index 0000000..89a424a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetVendor-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidPresetVendor: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresetVendor.json.in b/Tests/RunCMake/CMakePresets/InvalidPresetVendor.json.in
new file mode 100644
index 0000000..2a5d9ba
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresetVendor.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "InvalidPresetVendor",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "vendor": true
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresets-result.txt b/Tests/RunCMake/CMakePresets/InvalidPresets-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresets-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresets-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidPresets-stderr.txt
new file mode 100644
index 0000000..2b0f560
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresets-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidPresets: Invalid "configurePresets" field$
diff --git a/Tests/RunCMake/CMakePresets/InvalidPresets.json.in b/Tests/RunCMake/CMakePresets/InvalidPresets.json.in
new file mode 100644
index 0000000..facfd57
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidPresets.json.in
@@ -0,0 +1,4 @@
+{
+ "version": 1,
+ "configurePresets": {}
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidRoot-result.txt b/Tests/RunCMake/CMakePresets/InvalidRoot-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidRoot-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt
new file mode 100644
index 0000000..e5c434d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidRoot-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidRoot: Invalid root object$
diff --git a/Tests/RunCMake/CMakePresets/InvalidRoot.json.in b/Tests/RunCMake/CMakePresets/InvalidRoot.json.in
new file mode 100644
index 0000000..fe51488
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidRoot.json.in
@@ -0,0 +1 @@
+[]
diff --git a/Tests/RunCMake/CMakePresets/InvalidVariableValue-result.txt b/Tests/RunCMake/CMakePresets/InvalidVariableValue-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVariableValue-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidVariableValue-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidVariableValue-stderr.txt
new file mode 100644
index 0000000..0ab07c3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVariableValue-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidVariableValue: Invalid CMake variable definition$
diff --git a/Tests/RunCMake/CMakePresets/InvalidVariableValue.json.in b/Tests/RunCMake/CMakePresets/InvalidVariableValue.json.in
new file mode 100644
index 0000000..55c7644
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVariableValue.json.in
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "InvalidVariableValue",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "VAR": {
+ "value": []
+ }
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidVariables-result.txt b/Tests/RunCMake/CMakePresets/InvalidVariables-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVariables-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidVariables-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidVariables-stderr.txt
new file mode 100644
index 0000000..6d9102a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVariables-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidVariables: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/InvalidVariables.json.in b/Tests/RunCMake/CMakePresets/InvalidVariables.json.in
new file mode 100644
index 0000000..30dcaf0
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVariables.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "InvalidVariables",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": []
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidVendor-result.txt b/Tests/RunCMake/CMakePresets/InvalidVendor-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVendor-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidVendor-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidVendor-stderr.txt
new file mode 100644
index 0000000..af923f0
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVendor-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidVendor: Invalid root object$
diff --git a/Tests/RunCMake/CMakePresets/InvalidVendor.json.in b/Tests/RunCMake/CMakePresets/InvalidVendor.json.in
new file mode 100644
index 0000000..2315b72
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVendor.json.in
@@ -0,0 +1,5 @@
+{
+ "version": 1,
+ "vendor": true,
+ "configurePresets": []
+}
diff --git a/Tests/RunCMake/CMakePresets/InvalidVersion-result.txt b/Tests/RunCMake/CMakePresets/InvalidVersion-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVersion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/InvalidVersion-stderr.txt b/Tests/RunCMake/CMakePresets/InvalidVersion-stderr.txt
new file mode 100644
index 0000000..7e0fcfd
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVersion-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/InvalidVersion: Invalid "version" field$
diff --git a/Tests/RunCMake/CMakePresets/InvalidVersion.json.in b/Tests/RunCMake/CMakePresets/InvalidVersion.json.in
new file mode 100644
index 0000000..e6e19bc
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/InvalidVersion.json.in
@@ -0,0 +1,4 @@
+{
+ "version": "1.0",
+ "configurePresets": []
+}
diff --git a/Tests/RunCMake/CMakePresets/JSONParseError-result.txt b/Tests/RunCMake/CMakePresets/JSONParseError-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/JSONParseError-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt b/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt
new file mode 100644
index 0000000..a43bf77
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/JSONParseError-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/JSONParseError: JSON parse error$
diff --git a/Tests/RunCMake/CMakePresets/JSONParseError.json.in b/Tests/RunCMake/CMakePresets/JSONParseError.json.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/JSONParseError.json.in
diff --git a/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
new file mode 100644
index 0000000..1758f33
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresets-stdout.txt
@@ -0,0 +1,6 @@
+^Not searching for unused variables given on the command line\.
+Available presets:
+
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresets.json.in b/Tests/RunCMake/CMakePresets/ListPresets.json.in
new file mode 100644
index 0000000..c7646c6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresets.json.in
@@ -0,0 +1,36 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "zzzzzz",
+ "displayName": "Sleepy",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/zzzzzz"
+ },
+ {
+ "name": "aaaaaaaa",
+ "displayName": "Screaming",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/aaaaaaaa"
+ },
+ {
+ "name": "mmmmmm",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build/mmmmmm"
+ },
+ {
+ "name": "invalid-generator",
+ "generator": "Invalid Generator",
+ "binaryDir": "${sourceDir}/build/invalid"
+ },
+ {
+ "name": "invalid-macro",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${noexist}"
+ },
+ {
+ "name": "ListPresetsHidden",
+ "hidden": true
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsHidden-result.txt b/Tests/RunCMake/CMakePresets/ListPresetsHidden-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresetsHidden-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stderr.txt b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stderr.txt
new file mode 100644
index 0000000..1403814
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Cannot use hidden preset in [^
+]*/Tests/RunCMake/CMakePresets/ListPresetsHidden: "ListPresetsHidden"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
new file mode 100644
index 0000000..1758f33
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresetsHidden-stdout.txt
@@ -0,0 +1,6 @@
+^Not searching for unused variables given on the command line\.
+Available presets:
+
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-result.txt b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stderr.txt b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stderr.txt
new file mode 100644
index 0000000..eea1b99
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: No such preset in [^
+]*/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset: "ListPresetsNoSuchPreset"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
new file mode 100644
index 0000000..1758f33
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresetsNoSuchPreset-stdout.txt
@@ -0,0 +1,6 @@
+^Not searching for unused variables given on the command line\.
+Available presets:
+
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"$
diff --git a/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
new file mode 100644
index 0000000..1758f33
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/ListPresetsWorkingDir-stdout.txt
@@ -0,0 +1,6 @@
+^Not searching for unused variables given on the command line\.
+Available presets:
+
+ "zzzzzz" - Sleepy
+ "aaaaaaaa" - Screaming
+ "mmmmmm"$
diff --git a/Tests/RunCMake/CMakePresets/LowVersion-result.txt b/Tests/RunCMake/CMakePresets/LowVersion-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/LowVersion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt b/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt
new file mode 100644
index 0000000..92b3723
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/LowVersion-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/LowVersion: Unrecognized "version" field$
diff --git a/Tests/RunCMake/CMakePresets/LowVersion.json.in b/Tests/RunCMake/CMakePresets/LowVersion.json.in
new file mode 100644
index 0000000..e03afa9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/LowVersion.json.in
@@ -0,0 +1,4 @@
+{
+ "version": 0,
+ "configurePresets": []
+}
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredEmpty.cmake b/Tests/RunCMake/CMakePresets/MinimumRequiredEmpty.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredEmpty.cmake
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredEmpty.json.in b/Tests/RunCMake/CMakePresets/MinimumRequiredEmpty.json.in
new file mode 100644
index 0000000..37740ef
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredEmpty.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "cmakeMinimumRequired": {},
+ "configurePresets": [
+ {
+ "name": "MinimumRequiredEmpty",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-result.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-stderr.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-stderr.txt
new file mode 100644
index 0000000..6548caf
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid: Invalid "cmakeMinimumRequired" field$
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid.json.in b/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid.json.in
new file mode 100644
index 0000000..da79603
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredInvalid.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "cmakeMinimumRequired": "3.18",
+ "configurePresets": [
+ {
+ "name": "MinimumRequiredInvalid",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-result.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-stderr.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-stderr.txt
new file mode 100644
index 0000000..6036fe3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredMajor-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/MinimumRequiredMajor: "cmakeMinimumRequired" version too new$
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredMajor.json.in b/Tests/RunCMake/CMakePresets/MinimumRequiredMajor.json.in
new file mode 100644
index 0000000..a17cdf6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredMajor.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "cmakeMinimumRequired": {
+ "major": 1000
+ },
+ "configurePresets": [
+ {
+ "name": "MinimumRequiredMajor",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-result.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-stderr.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-stderr.txt
new file mode 100644
index 0000000..bdee4cd
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredMinor-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/MinimumRequiredMinor: "cmakeMinimumRequired" version too new$
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredMinor.json.in b/Tests/RunCMake/CMakePresets/MinimumRequiredMinor.json.in
new file mode 100644
index 0000000..33a8816
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredMinor.json.in
@@ -0,0 +1,14 @@
+{
+ "version": 1,
+ "cmakeMinimumRequired": {
+ "major": @CMAKE_MAJOR_VERSION@,
+ "minor": 1000
+ },
+ "configurePresets": [
+ {
+ "name": "MinimumRequiredMinor",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-result.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-stderr.txt b/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-stderr.txt
new file mode 100644
index 0000000..b5d3a39
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredPatch-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/MinimumRequiredPatch: "cmakeMinimumRequired" version too new$
diff --git a/Tests/RunCMake/CMakePresets/MinimumRequiredPatch.json.in b/Tests/RunCMake/CMakePresets/MinimumRequiredPatch.json.in
new file mode 100644
index 0000000..4a53f8d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/MinimumRequiredPatch.json.in
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "cmakeMinimumRequired": {
+ "major": @CMAKE_MAJOR_VERSION@,
+ "minor": @CMAKE_MINOR_VERSION@,
+ "patch": 50000000
+ },
+ "configurePresets": [
+ {
+ "name": "MinimumRequiredPatch",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/NoCMakePresets-result.txt b/Tests/RunCMake/CMakePresets/NoCMakePresets-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoCMakePresets-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoCMakePresets-stderr.txt b/Tests/RunCMake/CMakePresets/NoCMakePresets-stderr.txt
new file mode 100644
index 0000000..c807ffc
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoCMakePresets-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/NoCMakePresets: File not found$
diff --git a/Tests/RunCMake/CMakePresets/NoDebug-stdout.txt b/Tests/RunCMake/CMakePresets/NoDebug-stdout.txt
new file mode 100644
index 0000000..c23ab89
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoDebug-stdout.txt
@@ -0,0 +1,2 @@
+-- Configuring done
+-- Generating done
diff --git a/Tests/RunCMake/CMakePresets/NoDebug.cmake b/Tests/RunCMake/CMakePresets/NoDebug.cmake
new file mode 100644
index 0000000..f2b3d4a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoDebug.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/DebugBase.cmake)
+if(EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/CMakeLists.txt")
+ message(SEND_ERROR "Not debugging try_compile() did not work")
+endif()
diff --git a/Tests/RunCMake/CMakePresets/NoPresetArgument-result.txt b/Tests/RunCMake/CMakePresets/NoPresetArgument-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetArgument-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt
new file mode 100644
index 0000000..aef30d2
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetArgument-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: No preset specified for --preset$
diff --git a/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-result.txt b/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-stderr.txt
new file mode 100644
index 0000000..b525fc3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetBinaryDir-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/NoPresetBinaryDir: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/NoPresetBinaryDir.json.in b/Tests/RunCMake/CMakePresets/NoPresetBinaryDir.json.in
new file mode 100644
index 0000000..8989cfd
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetBinaryDir.json.in
@@ -0,0 +1,9 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "NoPresetBinaryDir",
+ "generator": "@RunCMake_GENERATOR@"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/NoPresetGenerator-result.txt b/Tests/RunCMake/CMakePresets/NoPresetGenerator-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetGenerator-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoPresetGenerator-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetGenerator-stderr.txt
new file mode 100644
index 0000000..6c0c9f7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetGenerator-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/NoPresetGenerator: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/NoPresetGenerator.json.in b/Tests/RunCMake/CMakePresets/NoPresetGenerator.json.in
new file mode 100644
index 0000000..74f83b7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetGenerator.json.in
@@ -0,0 +1,9 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "NoPresetGenerator",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/NoPresetName-result.txt b/Tests/RunCMake/CMakePresets/NoPresetName-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetName-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoPresetName-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresetName-stderr.txt
new file mode 100644
index 0000000..0ee338a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetName-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/NoPresetName: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/NoPresetName.json.in b/Tests/RunCMake/CMakePresets/NoPresetName.json.in
new file mode 100644
index 0000000..373591d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresetName.json.in
@@ -0,0 +1,9 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/NoPresets-result.txt b/Tests/RunCMake/CMakePresets/NoPresets-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresets-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoPresets-stderr.txt b/Tests/RunCMake/CMakePresets/NoPresets-stderr.txt
new file mode 100644
index 0000000..5ff3d33
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresets-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: No such preset in [^
+]*/Tests/RunCMake/CMakePresets/NoPresets: "NoPresets"$
diff --git a/Tests/RunCMake/CMakePresets/NoPresets-stdout.txt b/Tests/RunCMake/CMakePresets/NoPresets-stdout.txt
new file mode 100644
index 0000000..cb01a02
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresets-stdout.txt
@@ -0,0 +1 @@
+^Not searching for unused variables given on the command line\.$
diff --git a/Tests/RunCMake/CMakePresets/NoPresets.json.in b/Tests/RunCMake/CMakePresets/NoPresets.json.in
new file mode 100644
index 0000000..61a2092
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoPresets.json.in
@@ -0,0 +1,3 @@
+{
+ "version": 1
+}
diff --git a/Tests/RunCMake/CMakePresets/NoSuchMacro-result.txt b/Tests/RunCMake/CMakePresets/NoSuchMacro-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoSuchMacro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt b/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt
new file mode 100644
index 0000000..08fa87b
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoSuchMacro-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: Could not evaluate preset "NoSuchMacro": Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/NoSuchPreset-result.txt b/Tests/RunCMake/CMakePresets/NoSuchPreset-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoSuchPreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoSuchPreset-stderr.txt b/Tests/RunCMake/CMakePresets/NoSuchPreset-stderr.txt
new file mode 100644
index 0000000..9a2d0d5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoSuchPreset-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: No such preset in [^
+]*/Tests/RunCMake/CMakePresets/NoSuchPreset: "NoSuchPreset"$
diff --git a/Tests/RunCMake/CMakePresets/NoVariableValue-result.txt b/Tests/RunCMake/CMakePresets/NoVariableValue-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoVariableValue-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoVariableValue-stderr.txt b/Tests/RunCMake/CMakePresets/NoVariableValue-stderr.txt
new file mode 100644
index 0000000..cdab32f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoVariableValue-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/NoVariableValue: Invalid CMake variable definition$
diff --git a/Tests/RunCMake/CMakePresets/NoVariableValue.json.in b/Tests/RunCMake/CMakePresets/NoVariableValue.json.in
new file mode 100644
index 0000000..482700d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoVariableValue.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "NoVariableValue",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "VAR": {}
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/NoVersion-result.txt b/Tests/RunCMake/CMakePresets/NoVersion-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoVersion-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/NoVersion-stderr.txt b/Tests/RunCMake/CMakePresets/NoVersion-stderr.txt
new file mode 100644
index 0000000..d4f07e4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoVersion-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/NoVersion: No "version" field$
diff --git a/Tests/RunCMake/CMakePresets/NoVersion.json.in b/Tests/RunCMake/CMakePresets/NoVersion.json.in
new file mode 100644
index 0000000..3fe8332
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoVersion.json.in
@@ -0,0 +1,3 @@
+{
+ "configurePresets": []
+}
diff --git a/Tests/RunCMake/CMakePresets/NoWarningFlags-stderr.txt b/Tests/RunCMake/CMakePresets/NoWarningFlags-stderr.txt
new file mode 100644
index 0000000..a16d362
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoWarningFlags-stderr.txt
@@ -0,0 +1,23 @@
+^CMake Warning \(dev\) at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+ Dev warning
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakePresets/NoWarningFlags\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Deprecation Warning at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+ Deprecation warning
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakePresets/NoWarningFlags\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Warning:
+ Manually-specified variables were not used by the project:
+
+ RunCMake_GENERATOR
+ UNUSED_VARIABLE$
diff --git a/Tests/RunCMake/CMakePresets/NoWarningFlags.cmake b/Tests/RunCMake/CMakePresets/NoWarningFlags.cmake
new file mode 100644
index 0000000..5de7687
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/NoWarningFlags.cmake
@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/WarningsBase.cmake)
diff --git a/Tests/RunCMake/CMakePresets/PresetNotObject-result.txt b/Tests/RunCMake/CMakePresets/PresetNotObject-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/PresetNotObject-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/PresetNotObject-stderr.txt b/Tests/RunCMake/CMakePresets/PresetNotObject-stderr.txt
new file mode 100644
index 0000000..6604a14
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/PresetNotObject-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/PresetNotObject: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/PresetNotObject.json.in b/Tests/RunCMake/CMakePresets/PresetNotObject.json.in
new file mode 100644
index 0000000..d5892fc
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/PresetNotObject.json.in
@@ -0,0 +1,6 @@
+{
+ "version": 1,
+ "configurePresets": [
+ []
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
new file mode 100644
index 0000000..f591964
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -0,0 +1,212 @@
+include(RunCMake)
+
+# Fix Visual Studio generator name
+if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ")
+ set(RunCMake_GENERATOR "${CMAKE_MATCH_1}")
+endif()
+
+function(run_cmake_presets name)
+ set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}")
+ set(_source_arg "${RunCMake_TEST_SOURCE_DIR}")
+ if(CMakePresets_RELATIVE_SOURCE)
+ set(_source_arg "../${name}")
+ endif()
+ file(REMOVE_RECURSE "${RunCMake_TEST_SOURCE_DIR}")
+ file(MAKE_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}")
+ configure_file("${RunCMake_SOURCE_DIR}/CMakeLists.txt.in" "${RunCMake_TEST_SOURCE_DIR}/CMakeLists.txt" @ONLY)
+
+ if(NOT CMakePresets_FILE)
+ set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/${name}.json.in")
+ endif()
+ if(EXISTS "${CMakePresets_FILE}")
+ configure_file("${CMakePresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakePresets.json" @ONLY)
+ endif()
+
+ if(NOT CMakeUserPresets_FILE)
+ set(CMakeUserPresets_FILE "${RunCMake_SOURCE_DIR}/${name}User.json.in")
+ endif()
+ if(EXISTS "${CMakeUserPresets_FILE}")
+ configure_file("${CMakeUserPresets_FILE}" "${RunCMake_TEST_SOURCE_DIR}/CMakeUserPresets.json" @ONLY)
+ endif()
+
+ set(_s_arg -S)
+ if(CMakePresets_NO_S_ARG)
+ set(_s_arg)
+ endif()
+ set(_source_args ${_s_arg} ${_source_arg})
+ if(CMakePresets_NO_SOURCE_ARGS)
+ set(_source_args)
+ endif()
+ set(_unused_cli --no-warn-unused-cli)
+ if(CMakePresets_WARN_UNUSED_CLI)
+ set(_unused_cli)
+ endif()
+
+ set(RunCMake_TEST_COMMAND ${CMAKE_COMMAND}
+ ${_source_args}
+ -DRunCMake_TEST=${name}
+ -DRunCMake_GENERATOR=${RunCMake_GENERATOR}
+ -DCMAKE_MAKE_PROGRAM=${RunCMake_MAKE_PROGRAM}
+ ${_unused_cli}
+ --preset=${name}
+ ${ARGN}
+ )
+ run_cmake(${name})
+endfunction()
+
+# Test CMakePresets.json errors
+run_cmake_presets(NoCMakePresets)
+run_cmake_presets(JSONParseError)
+run_cmake_presets(InvalidRoot)
+run_cmake_presets(NoVersion)
+run_cmake_presets(InvalidVersion)
+run_cmake_presets(LowVersion)
+run_cmake_presets(HighVersion)
+run_cmake_presets(InvalidVendor)
+run_cmake_presets(NoPresets)
+run_cmake_presets(InvalidPresets)
+run_cmake_presets(PresetNotObject)
+run_cmake_presets(NoPresetName)
+run_cmake_presets(InvalidPresetName)
+run_cmake_presets(EmptyPresetName)
+run_cmake_presets(NoPresetGenerator)
+run_cmake_presets(InvalidPresetGenerator)
+run_cmake_presets(NoPresetBinaryDir)
+run_cmake_presets(InvalidPresetBinaryDir)
+run_cmake_presets(InvalidVariables)
+run_cmake_presets(VariableNotObject)
+run_cmake_presets(NoVariableValue)
+run_cmake_presets(InvalidVariableValue)
+run_cmake_presets(ExtraRootField)
+run_cmake_presets(ExtraPresetField)
+run_cmake_presets(ExtraVariableField)
+run_cmake_presets(InvalidPresetVendor)
+run_cmake_presets(DuplicatePresets)
+run_cmake_presets(CyclicInheritance0)
+run_cmake_presets(CyclicInheritance1)
+run_cmake_presets(CyclicInheritance2)
+run_cmake_presets(InvalidInheritance)
+run_cmake_presets(ErrorNoWarningDev)
+run_cmake_presets(ErrorNoWarningDeprecated)
+run_cmake_presets(InvalidCMakeGeneratorConfig)
+run_cmake_presets(UnknownCMakeGeneratorConfig)
+
+# Test cmakeMinimumRequired field
+run_cmake_presets(MinimumRequiredInvalid)
+run_cmake_presets(MinimumRequiredEmpty)
+run_cmake_presets(MinimumRequiredMajor)
+run_cmake_presets(MinimumRequiredMinor)
+run_cmake_presets(MinimumRequiredPatch)
+
+# Test properly working CMakePresets.json
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/CMakePresets.json.in")
+unset(ENV{TEST_ENV})
+unset(ENV{TEST_ENV_REF})
+unset(ENV{TEST_D_ENV_REF})
+set(ENV{TEST_ENV_OVERRIDE} "This environment variable will be overridden")
+set(ENV{TEST_PENV} "Process environment variable")
+set(ENV{TEST_ENV_REF_PENV} "suffix")
+run_cmake_presets(Good "-DTEST_OVERRIDE_1=Overridden value" "-DTEST_OVERRIDE_2:STRING=Overridden value" -C "${RunCMake_SOURCE_DIR}/CacheOverride.cmake" "-UTEST_UNDEF")
+unset(ENV{TEST_ENV_OVERRIDE})
+unset(ENV{TEST_PENV})
+unset(ENV{TEST_ENV_REF_PENV})
+run_cmake_presets(GoodNoArgs)
+file(REMOVE_RECURSE ${RunCMake_BINARY_DIR}/GoodBinaryUp-build)
+run_cmake_presets(GoodBinaryUp)
+set(CMakePresets_RELATIVE_SOURCE TRUE)
+run_cmake_presets(GoodBinaryRelative)
+unset(CMakePresets_RELATIVE_SOURCE)
+run_cmake_presets(GoodSpaces "--preset=Good Spaces")
+if(WIN32)
+ run_cmake_presets(GoodWindowsBackslash)
+endif()
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/GoodBOM.json.in")
+run_cmake_presets(GoodBOM)
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/CMakePresets.json.in")
+file(REMOVE_RECURSE ${RunCMake_BINARY_DIR}/GoodBinaryCmdLine-build)
+run_cmake_presets(GoodBinaryCmdLine -B ${RunCMake_BINARY_DIR}/GoodBinaryCmdLine-build)
+run_cmake_presets(GoodGeneratorCmdLine -G ${RunCMake_GENERATOR})
+run_cmake_presets(InvalidGeneratorCmdLine -G "Invalid Generator")
+set(CMakePresets_NO_S_ARG TRUE)
+run_cmake_presets(GoodNoS)
+unset(CMakePresets_NO_S_ARG)
+run_cmake_presets(GoodInheritanceParent)
+run_cmake_presets(GoodInheritanceChild)
+run_cmake_presets(GoodInheritanceOverride)
+run_cmake_presets(GoodInheritanceMulti)
+run_cmake_presets(GoodInheritanceMultiSecond)
+run_cmake_presets(GoodInheritanceMacro)
+
+# Test bad preset arguments
+run_cmake_presets(UnclosedMacro)
+run_cmake_presets(NoSuchMacro)
+run_cmake_presets(VendorMacro)
+run_cmake_presets(InvalidGenerator)
+run_cmake_presets(EnvCycle)
+
+# Test Visual Studio-specific stuff
+if(RunCMake_GENERATOR MATCHES "^Visual Studio ")
+ run_cmake_presets(VisualStudioGeneratorArch)
+ run_cmake_presets(VisualStudioWin32)
+ run_cmake_presets(VisualStudioWin64)
+ run_cmake_presets(VisualStudioWin32Override -A x64)
+ if(NOT RunCMake_GENERATOR STREQUAL "Visual Studio 9 2008")
+ run_cmake_presets(VisualStudioToolset)
+ run_cmake_presets(VisualStudioToolsetOverride -T "Test Toolset")
+ run_cmake_presets(VisualStudioInheritanceParent)
+ run_cmake_presets(VisualStudioInheritanceChild)
+ run_cmake_presets(VisualStudioInheritanceOverride)
+ run_cmake_presets(VisualStudioInheritanceMulti)
+ run_cmake_presets(VisualStudioInheritanceMultiSecond)
+ endif()
+else()
+ run_cmake_presets(CMakeGeneratorConfigNone)
+ run_cmake_presets(CMakeGeneratorConfigDefault)
+ run_cmake_presets(CMakeGeneratorConfigIgnore)
+endif()
+
+# Test bad command line arguments
+run_cmake_presets(NoSuchPreset)
+run_cmake_presets(NoPresetArgument --preset=)
+run_cmake_presets(UseHiddenPreset)
+
+# Test CMakeUserPresets.json
+unset(CMakePresets_FILE)
+run_cmake_presets(GoodUserOnly)
+run_cmake_presets(GoodUserFromMain)
+run_cmake_presets(GoodUserFromUser)
+
+# Test CMakeUserPresets.json errors
+run_cmake_presets(UserDuplicateInUser)
+run_cmake_presets(UserDuplicateCross)
+run_cmake_presets(UserInheritance)
+
+# Test listing presets
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/ListPresets.json.in")
+run_cmake_presets(ListPresets --list-presets)
+
+set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/ListPresetsWorkingDir")
+set(RunCMake_TEST_NO_CLEAN 1)
+set(CMakePresets_NO_SOURCE_ARGS 1)
+run_cmake_presets(ListPresetsWorkingDir --list-presets)
+unset(CMakePresets_NO_SOURCE_ARGS)
+unset(RunCMake_TEST_NO_CLEAN)
+unset(RunCMake_TEST_BINARY_DIR)
+
+run_cmake_presets(ListPresetsNoSuchPreset)
+run_cmake_presets(ListPresetsHidden)
+
+# Test warning and error flags
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Warnings.json.in")
+set(CMakePresets_WARN_UNUSED_CLI 1)
+run_cmake_presets(NoWarningFlags)
+run_cmake_presets(WarningFlags)
+run_cmake_presets(DisableWarningFlags)
+run_cmake_presets(ErrorDev)
+run_cmake_presets(ErrorDeprecated)
+unset(CMakePresets_WARN_UNUSED_CLI)
+
+# Test debug
+set(CMakePresets_FILE "${RunCMake_SOURCE_DIR}/Debug.json.in")
+run_cmake_presets(NoDebug)
+run_cmake_presets(Debug)
diff --git a/Tests/RunCMake/CMakePresets/TestVariable.cmake b/Tests/RunCMake/CMakePresets/TestVariable.cmake
new file mode 100644
index 0000000..934af52
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/TestVariable.cmake
@@ -0,0 +1,25 @@
+function(test_variable name expected_type expected_value)
+ if(NOT DEFINED "${name}")
+ message(SEND_ERROR "${name} is not defined")
+ elseif(NOT "${${name}}" STREQUAL expected_value)
+ message(SEND_ERROR "Expected value of ${name}: \"${expected_value}\"\nActual value: \"${${name}}\"")
+ endif()
+ if(expected_type)
+ if(NOT DEFINED "CACHE{${name}}")
+ message(SEND_ERROR "Cache entry ${name} does not exist")
+ else()
+ get_property(type CACHE ${name} PROPERTY TYPE)
+ if(NOT type STREQUAL expected_type)
+ message(SEND_ERROR "Expected type of ${name}: \"${expected_type}\"\nActual type: \"${type}\"")
+ endif()
+ endif()
+ endif()
+endfunction()
+
+function(test_environment_variable name expected_value)
+ if(NOT DEFINED "ENV{${name}}")
+ message(SEND_ERROR "Environment variable ${name} is not defined")
+ elseif(NOT "$ENV{${name}}" STREQUAL expected_value)
+ message(SEND_ERROR "Expected value of environment variable ${name}: \"${expected_value}\"\nActual value: \"$ENV{${name}}\"")
+ endif()
+endfunction()
diff --git a/Tests/RunCMake/CMakePresets/UnclosedMacro-result.txt b/Tests/RunCMake/CMakePresets/UnclosedMacro-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnclosedMacro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt b/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt
new file mode 100644
index 0000000..248510d
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnclosedMacro-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: Could not evaluate preset "UnclosedMacro": Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-result.txt b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-stderr.txt b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-stderr.txt
new file mode 100644
index 0000000..b1759b0
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig: Invalid preset$
diff --git a/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
new file mode 100644
index 0000000..900c6df
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UnknownCMakeGeneratorConfig.json.in
@@ -0,0 +1,11 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "UnknownCMakeGeneratorConfig",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cmakeGeneratorConfig": "unknown"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/UseHiddenPreset-result.txt b/Tests/RunCMake/CMakePresets/UseHiddenPreset-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UseHiddenPreset-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/UseHiddenPreset-stderr.txt b/Tests/RunCMake/CMakePresets/UseHiddenPreset-stderr.txt
new file mode 100644
index 0000000..45b4cd4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UseHiddenPreset-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Cannot use hidden preset in [^
+]*/Tests/RunCMake/CMakePresets/UseHiddenPreset: "UseHiddenPreset"$
diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateCross-result.txt b/Tests/RunCMake/CMakePresets/UserDuplicateCross-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserDuplicateCross-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateCross-stderr.txt b/Tests/RunCMake/CMakePresets/UserDuplicateCross-stderr.txt
new file mode 100644
index 0000000..125265f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserDuplicateCross-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/UserDuplicateCross: Duplicate presets$
diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateCross.json.in b/Tests/RunCMake/CMakePresets/UserDuplicateCross.json.in
new file mode 100644
index 0000000..172cfba
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserDuplicateCross.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "UserDuplicateCross",
+ "generator": "@RunCMake_GENERATOR",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateCrossUser.json.in b/Tests/RunCMake/CMakePresets/UserDuplicateCrossUser.json.in
new file mode 100644
index 0000000..172cfba
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserDuplicateCrossUser.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "UserDuplicateCross",
+ "generator": "@RunCMake_GENERATOR",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateInUser-result.txt b/Tests/RunCMake/CMakePresets/UserDuplicateInUser-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserDuplicateInUser-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateInUser-stderr.txt b/Tests/RunCMake/CMakePresets/UserDuplicateInUser-stderr.txt
new file mode 100644
index 0000000..1071b17
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserDuplicateInUser-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/UserDuplicateInUser: Duplicate presets$
diff --git a/Tests/RunCMake/CMakePresets/UserDuplicateInUserUser.json.in b/Tests/RunCMake/CMakePresets/UserDuplicateInUserUser.json.in
new file mode 100644
index 0000000..365fafe
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserDuplicateInUserUser.json.in
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "UserDuplicateInUser",
+ "generator": "@RunCMake_GENERATOR",
+ "binaryDir": "${sourceDir}/build"
+ },
+ {
+ "name": "UserDuplicateInUser",
+ "generator": "@RunCMake_GENERATOR",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/UserInheritance-result.txt b/Tests/RunCMake/CMakePresets/UserInheritance-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserInheritance-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/UserInheritance-stderr.txt b/Tests/RunCMake/CMakePresets/UserInheritance-stderr.txt
new file mode 100644
index 0000000..213215a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserInheritance-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/UserInheritance: Project preset inherits from user preset$
diff --git a/Tests/RunCMake/CMakePresets/UserInheritance.json.in b/Tests/RunCMake/CMakePresets/UserInheritance.json.in
new file mode 100644
index 0000000..d9973d7
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserInheritance.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "UserInheritance",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "inherits": [
+ "UserInheritanceUser"
+ ]
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/UserInheritanceUser.json.in b/Tests/RunCMake/CMakePresets/UserInheritanceUser.json.in
new file mode 100644
index 0000000..1321a73
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/UserInheritanceUser.json.in
@@ -0,0 +1,10 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "UserInheritanceUser",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build"
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/VariableNotObject-result.txt b/Tests/RunCMake/CMakePresets/VariableNotObject-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VariableNotObject-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/VariableNotObject-stderr.txt b/Tests/RunCMake/CMakePresets/VariableNotObject-stderr.txt
new file mode 100644
index 0000000..8cacb0a
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VariableNotObject-stderr.txt
@@ -0,0 +1,2 @@
+^CMake Error: Could not read presets from [^
+]*/Tests/RunCMake/CMakePresets/VariableNotObject: Invalid CMake variable definition$
diff --git a/Tests/RunCMake/CMakePresets/VariableNotObject.json.in b/Tests/RunCMake/CMakePresets/VariableNotObject.json.in
new file mode 100644
index 0000000..51298f5
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VariableNotObject.json.in
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "VariableNotObject",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "VAR": []
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/VendorMacro-result.txt b/Tests/RunCMake/CMakePresets/VendorMacro-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VendorMacro-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/VendorMacro-stderr.txt b/Tests/RunCMake/CMakePresets/VendorMacro-stderr.txt
new file mode 100644
index 0000000..2e98019
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VendorMacro-stderr.txt
@@ -0,0 +1 @@
+^CMake Error: Could not evaluate preset "VendorMacro": Invalid macro expansion$
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioGeneratorArch-result.txt b/Tests/RunCMake/CMakePresets/VisualStudioGeneratorArch-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioGeneratorArch-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioGeneratorArch-stderr.txt b/Tests/RunCMake/CMakePresets/VisualStudioGeneratorArch-stderr.txt
new file mode 100644
index 0000000..a311321
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioGeneratorArch-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error: Could not create named generator Visual Studio [^
+]* Win64
+Using platforms in Visual Studio generator names is not supported in CMakePresets\.json\.
+
+Generators
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioInheritanceChild.cmake b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceChild.cmake
new file mode 100644
index 0000000..d485ab3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceChild.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_NAME "" "Test Platform")
+test_variable(CMAKE_VS_PLATFORM_TOOLSET "" "Test Toolset")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioInheritanceMulti.cmake b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceMulti.cmake
new file mode 100644
index 0000000..d485ab3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceMulti.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_NAME "" "Test Platform")
+test_variable(CMAKE_VS_PLATFORM_TOOLSET "" "Test Toolset")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioInheritanceMultiSecond.cmake b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceMultiSecond.cmake
new file mode 100644
index 0000000..d485ab3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceMultiSecond.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_NAME "" "Test Platform")
+test_variable(CMAKE_VS_PLATFORM_TOOLSET "" "Test Toolset")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioInheritanceOverride.cmake b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceOverride.cmake
new file mode 100644
index 0000000..d485ab3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceOverride.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_NAME "" "Test Platform")
+test_variable(CMAKE_VS_PLATFORM_TOOLSET "" "Test Toolset")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioInheritanceParent.cmake b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceParent.cmake
new file mode 100644
index 0000000..d485ab3
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioInheritanceParent.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_NAME "" "Test Platform")
+test_variable(CMAKE_VS_PLATFORM_TOOLSET "" "Test Toolset")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioToolset.cmake b/Tests/RunCMake/CMakePresets/VisualStudioToolset.cmake
new file mode 100644
index 0000000..722e976
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioToolset.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_TOOLSET "" "Test Toolset")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioToolsetOverride.cmake b/Tests/RunCMake/CMakePresets/VisualStudioToolsetOverride.cmake
new file mode 100644
index 0000000..722e976
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioToolsetOverride.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_TOOLSET "" "Test Toolset")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioWin32.cmake b/Tests/RunCMake/CMakePresets/VisualStudioWin32.cmake
new file mode 100644
index 0000000..a1c61b4
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioWin32.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_NAME "" "Win32")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioWin32Override.cmake b/Tests/RunCMake/CMakePresets/VisualStudioWin32Override.cmake
new file mode 100644
index 0000000..b3464d6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioWin32Override.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_NAME "" "x64")
diff --git a/Tests/RunCMake/CMakePresets/VisualStudioWin64.cmake b/Tests/RunCMake/CMakePresets/VisualStudioWin64.cmake
new file mode 100644
index 0000000..b3464d6
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/VisualStudioWin64.cmake
@@ -0,0 +1,3 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+test_variable(CMAKE_VS_PLATFORM_NAME "" "x64")
diff --git a/Tests/RunCMake/CMakePresets/WarningFlags-stderr.txt b/Tests/RunCMake/CMakePresets/WarningFlags-stderr.txt
new file mode 100644
index 0000000..6e488a9
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/WarningFlags-stderr.txt
@@ -0,0 +1,34 @@
+^CMake Warning \(dev\) at [^
+]*/Modules/[^/
+]*:[0-9]+ \([a-zA-Z_][a-zA-Z0-9_]*\):
+ uninitialized variable '[^
+]*'
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(project\)
+This warning is for project developers\. Use -Wno-dev to suppress it\..*
+CMake Warning \(dev\) at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+ Dev warning
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakePresets/WarningFlags\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.
+
+CMake Deprecation Warning at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(message\):
+ Deprecation warning
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakePresets/WarningFlags\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+
+
+CMake Warning \(dev\) at [^
+]*/Tests/RunCMake/CMakePresets/WarningsBase\.cmake:[0-9]+ \(set\):
+ uninitialized variable 'UNINITIALIZED_VARIABLE'
+Call Stack \(most recent call first\):
+ [^
+]*/Tests/RunCMake/CMakePresets/WarningFlags\.cmake:[0-9]+ \(include\)
+ CMakeLists\.txt:[0-9]+ \(include\)
+This warning is for project developers\. Use -Wno-dev to suppress it\.$
diff --git a/Tests/RunCMake/CMakePresets/WarningFlags.cmake b/Tests/RunCMake/CMakePresets/WarningFlags.cmake
new file mode 100644
index 0000000..5de7687
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/WarningFlags.cmake
@@ -0,0 +1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/WarningsBase.cmake)
diff --git a/Tests/RunCMake/CMakePresets/Warnings.json.in b/Tests/RunCMake/CMakePresets/Warnings.json.in
new file mode 100644
index 0000000..40ec6ce
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/Warnings.json.in
@@ -0,0 +1,50 @@
+{
+ "version": 1,
+ "configurePresets": [
+ {
+ "name": "NoWarningFlags",
+ "generator": "@RunCMake_GENERATOR@",
+ "binaryDir": "${sourceDir}/build",
+ "cacheVariables": {
+ "UNUSED_VARIABLE": "Unused"
+ }
+ },
+ {
+ "name": "WarningFlags",
+ "inherits": "NoWarningFlags",
+ "warnings": {
+ "dev": true,
+ "deprecated": true,
+ "uninitialized": true,
+ "unusedCli": false,
+ "systemVars": true
+ }
+ },
+ {
+ "name": "DisableWarningFlags",
+ "inherits": "NoWarningFlags",
+ "warnings": {
+ "dev": false,
+ "deprecated": false,
+ "unusedCli": false
+ }
+ },
+ {
+ "name": "ErrorDev",
+ "inherits": "NoWarningFlags",
+ "errors": {
+ "dev": true
+ }
+ },
+ {
+ "name": "ErrorDeprecated",
+ "inherits": "NoWarningFlags",
+ "warnings": {
+ "dev": false
+ },
+ "errors": {
+ "deprecated": true
+ }
+ }
+ ]
+}
diff --git a/Tests/RunCMake/CMakePresets/WarningsBase.cmake b/Tests/RunCMake/CMakePresets/WarningsBase.cmake
new file mode 100644
index 0000000..1a434dc
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/WarningsBase.cmake
@@ -0,0 +1,3 @@
+message(AUTHOR_WARNING "Dev warning")
+message(DEPRECATION "Deprecation warning")
+set(_uninitialized "${UNINITIALIZED_VARIABLE}")
diff --git a/Tests/RunCMake/CMakePresets/main.c b/Tests/RunCMake/CMakePresets/main.c
new file mode 100644
index 0000000..8488f4e
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/CommandLine/NoArgs-stdout.txt b/Tests/RunCMake/CommandLine/NoArgs-stdout.txt
index f1dafc8..50f7d9d 100644
--- a/Tests/RunCMake/CommandLine/NoArgs-stdout.txt
+++ b/Tests/RunCMake/CommandLine/NoArgs-stdout.txt
@@ -3,6 +3,7 @@
cmake \[options\] <path-to-source>
cmake \[options\] <path-to-existing-build>
cmake \[options\] -S <path-to-source> -B <path-to-build>
+ cmake \[options\] -S <path-to-source> --preset=<preset-name>
Specify a source directory to \(re-\)generate a build system for it in the
current working directory. Specify an existing build directory to