diff --git a/Source/cmCMakePresetsFile.cxx b/Source/cmCMakePresetsFile.cxx
index 2f9972c381c663498b3b4bace7013ec610705fcf..fd578faef79fd736d3ad0f981e636b66a3d0a138 100644
--- a/Source/cmCMakePresetsFile.cxx
+++ b/Source/cmCMakePresetsFile.cxx
@@ -197,11 +197,13 @@ bool ExpandMacros(const cmCMakePresetsFile& file,
   std::string binaryDir = preset.BinaryDir;
   CHECK_EXPAND(out, binaryDir, macroExpanders, file.GetVersion(preset))
 
-  if (!cmSystemTools::FileIsFullPath(binaryDir)) {
-    binaryDir = cmStrCat(file.SourceDir, '/', binaryDir);
+  if (!binaryDir.empty()) {
+    if (!cmSystemTools::FileIsFullPath(binaryDir)) {
+      binaryDir = cmStrCat(file.SourceDir, '/', binaryDir);
+    }
+    out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
+    cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
   }
-  out->BinaryDir = cmSystemTools::CollapseFullPath(binaryDir);
-  cmSystemTools::ConvertToUnixSlashes(out->BinaryDir);
 
   if (!preset.InstallDir.empty()) {
     std::string installDir = preset.InstallDir;
diff --git a/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.cmake b/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..ae8a0def19f5bdf42500864f71943461080f2398
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.cmake
@@ -0,0 +1,4 @@
+include(${CMAKE_CURRENT_LIST_DIR}/TestVariable.cmake)
+
+get_filename_component(_parent_dir "${CMAKE_SOURCE_DIR}" DIRECTORY)
+test_variable(CMAKE_BINARY_DIR "" "${_parent_dir}/OptionalBinaryDirFieldNoS-build")
diff --git a/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.json.in b/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.json.in
new file mode 100644
index 0000000000000000000000000000000000000000..0e3addd560b57a5d9175a8cb3fa321bc5e488a27
--- /dev/null
+++ b/Tests/RunCMake/CMakePresets/OptionalBinaryDirFieldNoS.json.in
@@ -0,0 +1,9 @@
+{
+  "version": 3,
+  "configurePresets": [
+    {
+      "name": "OptionalBinaryDirFieldNoS",
+      "generator": "@RunCMake_GENERATOR@"
+    }
+  ]
+}
diff --git a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
index 3b9806ab7efea3897e68359c249b588284bd40dd..31bd8a4453626b3b2d7b404b6e19d55f3c509ab9 100644
--- a/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CMakePresets/RunCMakeTest.cmake
@@ -312,6 +312,11 @@ unset(CMakePresets_FILE)
 # Test optional generator and buildDir fields
 run_cmake_presets(OptionalBinaryDirField -B "${RunCMake_BINARY_DIR}/OptionalBinaryDirField/build")
 run_cmake_presets(OptionalGeneratorField -G "${RunCMake_GENERATOR}")
+set(CMakePresets_NO_S_ARG TRUE)
+set(CMakePresets_SOURCE_ARG "../OptionalBinaryDirFieldNoS")
+run_cmake_presets(OptionalBinaryDirFieldNoS)
+unset(CMakePresets_SOURCE_ARG)
+unset(CMakePresets_NO_S_ARG)
 
 # Test the example from the documentation
 file(READ "${RunCMake_SOURCE_DIR}/../../../Help/manual/presets/example.json" _example)