Merge branch 'cmake-option-parsing' into release-3.13

Merge-request: !2799
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 1aff5eb..74542df 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -609,16 +609,13 @@
 }
 
 // Parse the args
-void cmake::SetArgs(const std::vector<std::string>& args,
-                    bool directoriesSetBefore)
+void cmake::SetArgs(const std::vector<std::string>& args)
 {
-  bool directoriesSet = directoriesSetBefore;
   bool haveToolset = false;
   bool havePlatform = false;
   for (unsigned int i = 1; i < args.size(); ++i) {
     std::string const& arg = args[i];
     if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) {
-      directoriesSet = true;
       std::string path = arg.substr(2);
       if (path.empty()) {
         ++i;
@@ -639,7 +636,6 @@
     } else if (arg.find("-O", 0) == 0) {
       // There is no local generate anymore.  Ignore -O option.
     } else if (arg.find("-B", 0) == 0) {
-      directoriesSet = true;
       std::string path = arg.substr(2);
       if (path.empty()) {
         ++i;
@@ -801,16 +797,27 @@
         this->SetGlobalGenerator(gen);
       }
     }
-    // no option assume it is the path to the source
+    // no option assume it is the path to the source or an existing build
     else {
-      directoriesSet = true;
       this->SetDirectoriesFromFile(arg.c_str());
     }
   }
-  if (!directoriesSet) {
-    this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+
+  const bool haveSourceDir = !this->GetHomeDirectory().empty();
+  const bool haveBinaryDir = !this->GetHomeOutputDirectory().empty();
+
+  if (this->CurrentWorkingMode == cmake::NORMAL_MODE && !haveSourceDir &&
+      !haveBinaryDir) {
+    cmSystemTools::Error("No source or binary directory provided");
+    return;
+  }
+
+  if (!haveSourceDir) {
     this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory());
   }
+  if (!haveBinaryDir) {
+    this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory());
+  }
 }
 
 void cmake::SetDirectoriesFromFile(const char* arg)
diff --git a/Source/cmake.h b/Source/cmake.h
index d3d0e80..5bca306 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -275,8 +275,7 @@
   int GetSystemInformation(std::vector<std::string>&);
 
   ///! Parse command line arguments
-  void SetArgs(const std::vector<std::string>&,
-               bool directoriesSetBefore = false);
+  void SetArgs(const std::vector<std::string>& args);
 
   ///! Is this cmake running as a result of a TRY_COMPILE command
   bool GetIsInTryCompile() const;
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 75dabde..e52f2b3 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -285,12 +285,12 @@
     } else if (cmHasLiteralPrefix(av[i], "-P")) {
       if (i == ac - 1) {
         cmSystemTools::Error("No script specified for argument -P");
-      } else {
-        workingMode = cmake::SCRIPT_MODE;
-        args.push_back(av[i]);
-        i++;
-        args.push_back(av[i]);
+        return 1;
       }
+      workingMode = cmake::SCRIPT_MODE;
+      args.push_back(av[i]);
+      i++;
+      args.push_back(av[i]);
     } else if (cmHasLiteralPrefix(av[i], "--find-package")) {
       workingMode = cmake::FIND_PACKAGE_MODE;
       args.push_back(av[i]);
diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
index b47abfb..32e20ac 100644
--- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
+++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake
@@ -4,17 +4,17 @@
 
 run_cmake_command(NoArgs ${CMAKE_COMMAND})
 run_cmake_command(Wizard ${CMAKE_COMMAND} -i)
-run_cmake_command(C-no-arg ${CMAKE_COMMAND} -C)
-run_cmake_command(C-no-file ${CMAKE_COMMAND} -C nosuchcachefile.txt)
-run_cmake_command(Cno-file ${CMAKE_COMMAND} -Cnosuchcachefile.txt)
+run_cmake_command(C-no-arg ${CMAKE_COMMAND} -B DummyBuildDir -C)
+run_cmake_command(C-no-file ${CMAKE_COMMAND} -B DummyBuildDir -C nosuchcachefile.txt)
+run_cmake_command(Cno-file ${CMAKE_COMMAND} -B DummyBuildDir -Cnosuchcachefile.txt)
 run_cmake_command(cache-no-file ${CMAKE_COMMAND} nosuchsubdir/CMakeCache.txt)
 run_cmake_command(lists-no-file ${CMAKE_COMMAND} nosuchsubdir/CMakeLists.txt)
-run_cmake_command(D-no-arg ${CMAKE_COMMAND} -D)
-run_cmake_command(D-no-src ${CMAKE_COMMAND} -D VAR=VALUE)
-run_cmake_command(Dno-src ${CMAKE_COMMAND} -DVAR=VALUE)
-run_cmake_command(U-no-arg ${CMAKE_COMMAND} -U)
-run_cmake_command(U-no-src ${CMAKE_COMMAND} -U VAR)
-run_cmake_command(Uno-src ${CMAKE_COMMAND} -UVAR)
+run_cmake_command(D-no-arg ${CMAKE_COMMAND} -B DummyBuildDir -D)
+run_cmake_command(D-no-src ${CMAKE_COMMAND} -B DummyBuildDir -D VAR=VALUE)
+run_cmake_command(Dno-src ${CMAKE_COMMAND} -B DummyBuildDir -DVAR=VALUE)
+run_cmake_command(U-no-arg ${CMAKE_COMMAND} -B DummyBuildDir -U)
+run_cmake_command(U-no-src ${CMAKE_COMMAND} -B DummyBuildDir -U VAR)
+run_cmake_command(Uno-src ${CMAKE_COMMAND} -B DummyBuildDir -UVAR)
 run_cmake_command(E-no-arg ${CMAKE_COMMAND} -E)
 run_cmake_command(E_capabilities ${CMAKE_COMMAND} -E capabilities)
 run_cmake_command(E_capabilities-arg ${CMAKE_COMMAND} -E capabilities --extra-arg)
@@ -32,8 +32,8 @@
 run_cmake_command(E___run_co_compile-no--- ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist command-does-not-exist)
 run_cmake_command(E___run_co_compile-no-cc ${CMAKE_COMMAND} -E __run_co_compile --iwyu=iwyu-does-not-exist --)
 
-run_cmake_command(G_no-arg ${CMAKE_COMMAND} -G)
-run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -G NoSuchGenerator)
+run_cmake_command(G_no-arg ${CMAKE_COMMAND} -B DummyBuildDir -G)
+run_cmake_command(G_bad-arg ${CMAKE_COMMAND} -B DummyBuildDir -G NoSuchGenerator)
 run_cmake_command(P_no-arg ${CMAKE_COMMAND} -P)
 run_cmake_command(P_no-file ${CMAKE_COMMAND} -P nosuchscriptfile.cmake)
 
@@ -59,6 +59,7 @@
 
   file(REMOVE_RECURSE "${binary_dir}")
   file(MAKE_DIRECTORY "${binary_dir}")
+  run_cmake_command(no-S-B ${CMAKE_COMMAND} -DFOO=BAR)
   run_cmake_command(S-arg ${CMAKE_COMMAND} -S ${source_dir} ${binary_dir})
   run_cmake_command(S-arg-reverse-order ${CMAKE_COMMAND} ${binary_dir} -S${source_dir} )
   run_cmake_command(S-no-arg ${CMAKE_COMMAND} -S )
@@ -328,9 +329,9 @@
 run_cmake(Wno-dev)
 unset(RunCMake_TEST_OPTIONS)
 
-run_cmake_command(W_bad-arg1 ${CMAKE_COMMAND} -W)
-run_cmake_command(W_bad-arg2 ${CMAKE_COMMAND} -Wno-)
-run_cmake_command(W_bad-arg3 ${CMAKE_COMMAND} -Werror=)
+run_cmake_command(W_bad-arg1 ${CMAKE_COMMAND} -B DummyBuildDir -W)
+run_cmake_command(W_bad-arg2 ${CMAKE_COMMAND} -B DummyBuildDir -Wno-)
+run_cmake_command(W_bad-arg3 ${CMAKE_COMMAND} -B DummyBuildDir -Werror=)
 
 set(RunCMake_TEST_OPTIONS --debug-output)
 run_cmake(debug-output)
diff --git a/Tests/RunCMake/CommandLine/no-S-B-result.txt b/Tests/RunCMake/CommandLine/no-S-B-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/no-S-B-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/CommandLine/no-S-B-stderr.txt b/Tests/RunCMake/CommandLine/no-S-B-stderr.txt
new file mode 100644
index 0000000..7a94307
--- /dev/null
+++ b/Tests/RunCMake/CommandLine/no-S-B-stderr.txt
@@ -0,0 +1 @@
+CMake Error: No source or binary directory provided