From 19296f507dcc96b12909d6ebc7262019ee9b3fbc Mon Sep 17 00:00:00 2001 From: William Allen Date: Mon, 17 Nov 2025 12:58:39 -0500 Subject: [PATCH] cmake --build: Allow CLI build dir to override presets `cmake --build ` and `cmake --build --preset ` are currently mutually exclusive options. This commit allows `` to override the build directory specified in a preset. This change allows the requirement for each build preset to have a configure preset to be dropped in a future commit. Closes: #27384 --- Help/manual/cmake.1.rst | 10 +++++--- .../dev/build-dir-override-presets.rst | 6 +++++ Source/cmake.cxx | 2 +- ...irectoryOverride-build-override-result.txt | 1 + ...irectoryOverride-build-override-stderr.txt | 2 ++ .../BuildDirectoryOverride.json.in | 24 ++++++++++++++++++ .../CMakePresetsBuild/RunCMakeTest.cmake | 25 ++++++++++--------- 7 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 Help/release/dev/build-dir-override-presets.rst create mode 100644 Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-result.txt create mode 100644 Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-stderr.txt create mode 100644 Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride.json.in diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 316ba25ac3..cdd14555a1 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -790,9 +790,13 @@ following options: .. option:: --preset , --preset= Use a build preset to specify build options. The project binary directory - is inferred from the ``configurePreset`` key. The current working directory - must contain CMake preset files. - See :manual:`preset ` for more details. + is inferred from the ``configurePreset`` key unless a directory is specified + after ``--build``. The current working directory must contain CMake preset + files. See :manual:`preset ` for more details. + +.. versionchanged:: 4.3 + ``cmake --build`` now supports specifying a build directory and + preset together. .. option:: --list-presets diff --git a/Help/release/dev/build-dir-override-presets.rst b/Help/release/dev/build-dir-override-presets.rst new file mode 100644 index 0000000000..60ae9b9708 --- /dev/null +++ b/Help/release/dev/build-dir-override-presets.rst @@ -0,0 +1,6 @@ +build-dir-override-presets +-------------------------- + +* :option:`cmake --build` now supports specifying a build directory and + preset together. The build preset will be used with the explicit + build directory substituted. diff --git a/Source/cmake.cxx b/Source/cmake.cxx index b3a1f79efc..0c0ecf2feb 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3898,7 +3898,7 @@ int cmake::Build(int jobs, std::string dir, std::vector targets, return 1; } - if (!expandedConfigurePreset->BinaryDir.empty()) { + if (dir.empty() && !expandedConfigurePreset->BinaryDir.empty()) { dir = expandedConfigurePreset->BinaryDir; } diff --git a/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-result.txt b/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-stderr.txt b/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-stderr.txt new file mode 100644 index 0000000000..fbd9416468 --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-stderr.txt @@ -0,0 +1,2 @@ +^Error: [^ +]*/Tests/RunCMake/build2 is not a directory$ diff --git a/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride.json.in b/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride.json.in new file mode 100644 index 0000000000..66e8e4225a --- /dev/null +++ b/Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride.json.in @@ -0,0 +1,24 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 20, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default", + "binaryDir": "${sourceDir}/build", + "generator": "@RunCMake_GENERATOR@", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + } + ], + "buildPresets": [ + { + "name": "override", + "configurePreset": "default" + } + ] +} diff --git a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake index 1ededc1a60..85d3baf11b 100644 --- a/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakePresetsBuild/RunCMakeTest.cmake @@ -5,7 +5,7 @@ if(RunCMake_GENERATOR MATCHES "^(Visual Studio [0-9]+ [0-9]+) ") set(RunCMake_GENERATOR "${CMAKE_MATCH_1}") endif() -function(run_cmake_build_presets name CMakePresetsBuild_CONFIGURE_PRESETS CMakePresetsBuild_BUILD_PRESETS) +function(run_cmake_build_presets name CMakePresetsBuild_CONFIGURE_PRESETS CMakePresetsBuild_BUILD_PRESETS CMakePresetsBuild_BUILD_DIR_OVERRIDE) set(RunCMake_TEST_SOURCE_DIR "${RunCMake_BINARY_DIR}/${name}") set(RunCMake_TEST_BINARY_DIR "${RunCMake_TEST_SOURCE_DIR}/build") set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_SOURCE_DIR}") @@ -50,11 +50,11 @@ function(run_cmake_build_presets name CMakePresetsBuild_CONFIGURE_PRESETS CMakeP if(eq) run_cmake_command(${name}-build-${BUILD_PRESET} - ${CMAKE_COMMAND} "--build" "--preset=${BUILD_PRESET}" ${ARGN}) + ${CMAKE_COMMAND} "--build" ${CMakePresetsBuild_BUILD_DIR_OVERRIDE} "--preset=${BUILD_PRESET}" ${ARGN}) set(eq 0) else() run_cmake_command(${name}-build-${BUILD_PRESET} - ${CMAKE_COMMAND} "--build" "--preset" "${BUILD_PRESET}" ${ARGN}) + ${CMAKE_COMMAND} "--build" ${CMakePresetsBuild_BUILD_DIR_OVERRIDE} "--preset" "${BUILD_PRESET}" ${ARGN}) set(eq 1) endif() endforeach() @@ -70,19 +70,20 @@ else() set(Good_json_jobs [["jobs": 0,]]) endif() -run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject;singleTarget;initResolve") -run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset") -run_cmake_build_presets(Condition "default" "enabled;disabled") +run_cmake_build_presets(Good "default;other" "build-other;withEnvironment;noEnvironment;macros;vendorObject;singleTarget;initResolve" "") +run_cmake_build_presets(InvalidConfigurePreset "default" "badConfigurePreset" "") +run_cmake_build_presets(Condition "default" "enabled;disabled" "") set(CMakePresetsBuild_BUILD_ONLY 1) -run_cmake_build_presets(ListPresets "x" "x" "--list-presets") -run_cmake_build_presets(NoConfigurePreset "x" "noConfigurePreset") -run_cmake_build_presets(Invalid "x" "hidden;vendorMacro") +run_cmake_build_presets(ListPresets "x" "x" "--list-presets" "") +run_cmake_build_presets(NoConfigurePreset "x" "noConfigurePreset" "") +run_cmake_build_presets(Invalid "x" "hidden;vendorMacro" "") +run_cmake_build_presets(BuildDirectoryOverride "" "override" "${RunCMake_BINARY_DIR}/../build2") set(CMakePresets_SCHEMA_EXPECTED_RESULT 1) -run_cmake_build_presets(PresetsUnsupported "x" "x") -run_cmake_build_presets(ConditionFuture "x" "conditionFuture") +run_cmake_build_presets(PresetsUnsupported "x" "x" "") +run_cmake_build_presets(ConditionFuture "x" "conditionFuture" "") set(CMakePresets_SCHEMA_EXPECTED_RESULT 0) -run_cmake_build_presets(ConfigurePresetUnreachable "x" "x") +run_cmake_build_presets(ConfigurePresetUnreachable "x" "x" "") set(CMakePresetsBuild_BUILD_ONLY 0)