From a1adbc724336b0a4185e34b63e18de03a8b119cf Mon Sep 17 00:00:00 2001
From: Craig Scott <craig.scott@crascit.com>
Date: Sun, 13 Jan 2019 23:26:56 +1100
Subject: cmake: Stop processing if -P option lacks file name

While an error message was being logged, processing was
continuing nonetheless except with the -P argument omitted.
This could have allowed unintended effects if the remaining
arguments formed a valid set of command line options.
---
 Source/cmakemain.cxx | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

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 @@ int do_cmake(int ac, char const* const* av)
     } 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]);
-- 
cgit v0.12


From 27eb7c5bdb5bb8deefe1772675dc4819592bf036 Mon Sep 17 00:00:00 2001
From: Craig Scott <craig.scott@crascit.com>
Date: Sun, 13 Jan 2019 23:44:18 +1100
Subject: cmake: Ensure source and binary dirs are set

If only the source dir is provided, the binary dir is assumed
to be the working directory. If only the binary dir is provided
and it doesn't yet have a CMakeCache.txt to provide the
source dir, then the source dir is assumed to be the working
directory. This logic was not previously being handled
correctly when -S and/or -B options were involved.
Furthermore, when both were missing, no suitable error
message was provided and an empty string was used for
the build directory.

Fixes: #18707
---
 Source/cmake.cxx                              | 25 ++++++++++++++---------
 Source/cmake.h                                |  3 +--
 Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 29 ++++++++++++++-------------
 Tests/RunCMake/CommandLine/no-S-B-result.txt  |  1 +
 Tests/RunCMake/CommandLine/no-S-B-stderr.txt  |  1 +
 5 files changed, 34 insertions(+), 25 deletions(-)
 create mode 100644 Tests/RunCMake/CommandLine/no-S-B-result.txt
 create mode 100644 Tests/RunCMake/CommandLine/no-S-B-stderr.txt

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 @@ bool cmake::FindPackage(const std::vector<std::string>& args)
 }
 
 // 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 @@ void cmake::SetArgs(const std::vector<std::string>& args,
     } 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 @@ void cmake::SetArgs(const std::vector<std::string>& args,
         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 @@ public:
   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/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 @@ include(RunCMake)
 
 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-bad-iwyu ${CMAKE_COMMAND} -E __run_co_compi
 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 @@ function(run_ExplicitDirs)
 
   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 @@ set(RunCMake_TEST_OPTIONS -Wdev -Wno-dev)
 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
-- 
cgit v0.12