Browse Source

cmake --build: Allow CLI build dir to override presets

`cmake --build <dir>` and `cmake --build --preset <preset>` are currently
mutually exclusive options.  This commit allows `<dir>` 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
William Allen 2 weeks ago
parent
commit
19296f507d

+ 7 - 3
Help/manual/cmake.1.rst

@@ -790,9 +790,13 @@ following options:
 .. option:: --preset <preset>, --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 <cmake-presets(7)>` 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 <cmake-presets(7)>` for more details.
+
+.. versionchanged:: 4.3
+  ``cmake --build`` now supports specifying a build directory and
+    preset together.
 
 .. option:: --list-presets
 

+ 6 - 0
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.

+ 1 - 1
Source/cmake.cxx

@@ -3898,7 +3898,7 @@ int cmake::Build(int jobs, std::string dir, std::vector<std::string> targets,
       return 1;
     }
 
-    if (!expandedConfigurePreset->BinaryDir.empty()) {
+    if (dir.empty() && !expandedConfigurePreset->BinaryDir.empty()) {
       dir = expandedConfigurePreset->BinaryDir;
     }
 

+ 1 - 0
Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-result.txt

@@ -0,0 +1 @@
+1

+ 2 - 0
Tests/RunCMake/CMakePresetsBuild/BuildDirectoryOverride-build-override-stderr.txt

@@ -0,0 +1,2 @@
+^Error: [^
+]*/Tests/RunCMake/build2 is not a directory$

+ 24 - 0
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"
+    }
+  ]
+}

+ 13 - 12
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)