Commit 27eb7c5b authored by Craig Scott's avatar Craig Scott
Browse files

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
parent a1adbc72
......@@ -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()) {
......@@ -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()) {
......@@ -801,16 +797,27 @@ void cmake::SetArgs(const std::vector<std::string>& args,
// 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;
if (!directoriesSet) {
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");
if (!haveSourceDir) {
if (!haveBinaryDir) {
void cmake::SetDirectoriesFromFile(const char* arg)
......@@ -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;
......@@ -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_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)
CMake Error: No source or binary directory provided
  • mentioned in commit 1f411b0c

    Toggle commit list
  • We had some build scripts that implicitly used the working directory fallback when no directory was specified.

    Using a clone of as the working directory, on cmake 3.13.2 one could run

    cmake -G "Unix Makefiles"

    and the command would run correctly. cmake 3.13.3 gave an error: "CMake Error: No source or binary directory provided". Changing the command to:

    cmake -G "Unix Makefiles" .

    fixed the problem.

    Just figured this may be good to know in case other people were also relying on this bug :)

    Edited by Jeremy Day
  • mentioned in issue #18817 (closed)

    Toggle commit list
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment