From a10d63d5783275f9972aaa86d41071a1ddca7921 Mon Sep 17 00:00:00 2001 From: Robert Maynard Date: Thu, 6 Sep 2018 10:13:39 -0400 Subject: cmake: -S and -B can be used to specify source and build directories Document the previously internal option of '-B' and provide a matching source directory option with '-S'. Both '-B', and '-S' can be used independently of each other. --- Help/manual/OPTIONS_BUILD.txt | 8 +++ Help/manual/cmake.1.rst | 1 + Source/cmake.cxx | 57 +++++++++++++++++----- Source/cmake.h | 4 +- Source/cmakemain.cxx | 3 +- Tests/RunCMake/CommandLine/B-no-arg-result.txt | 1 + Tests/RunCMake/CommandLine/B-no-arg-stderr.txt | 1 + Tests/RunCMake/CommandLine/B-no-arg2-result.txt | 1 + Tests/RunCMake/CommandLine/B-no-arg2-stderr.txt | 1 + .../CommandLine/ExplicitDirs/CMakeLists.txt | 8 +++ Tests/RunCMake/CommandLine/NoArgs-stdout.txt | 1 + Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 25 ++++++++++ Tests/RunCMake/CommandLine/S-no-arg-result.txt | 1 + Tests/RunCMake/CommandLine/S-no-arg-stderr.txt | 1 + Tests/RunCMake/CommandLine/S-no-arg2-result.txt | 1 + Tests/RunCMake/CommandLine/S-no-arg2-stderr.txt | 1 + 16 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 Tests/RunCMake/CommandLine/B-no-arg-result.txt create mode 100644 Tests/RunCMake/CommandLine/B-no-arg-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/B-no-arg2-result.txt create mode 100644 Tests/RunCMake/CommandLine/B-no-arg2-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/ExplicitDirs/CMakeLists.txt create mode 100644 Tests/RunCMake/CommandLine/S-no-arg-result.txt create mode 100644 Tests/RunCMake/CommandLine/S-no-arg-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/S-no-arg2-result.txt create mode 100644 Tests/RunCMake/CommandLine/S-no-arg2-stderr.txt diff --git a/Help/manual/OPTIONS_BUILD.txt b/Help/manual/OPTIONS_BUILD.txt index 33d27af..baa73d5 100644 --- a/Help/manual/OPTIONS_BUILD.txt +++ b/Help/manual/OPTIONS_BUILD.txt @@ -1,3 +1,11 @@ +``-S `` + Path to root directory of the CMake project to build. + +``-B `` + Path to directory which CMake will use as the root of build directory. + + If the directory doesn't already exist CMake will make it. + ``-C `` Pre-load a script to populate the cache. diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 177acd4..9fe0c0b 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -9,6 +9,7 @@ Synopsis .. parsed-literal:: cmake [] { | } + cmake [] -S -B cmake [{-D =}...] -P cmake --build [...] [-- ...] cmake --open diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 1bf8f7d..68e4506 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -611,19 +611,43 @@ void cmake::SetArgs(const std::vector& args, bool havePlatform = false; for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; - if (arg.find("-H", 0) == 0) { + if (arg.find("-H", 0) == 0 || arg.find("-S", 0) == 0) { directoriesSet = true; std::string path = arg.substr(2); + if (path.empty()) { + ++i; + if (i >= args.size()) { + cmSystemTools::Error("No source directory specified for -S"); + return; + } + path = args[i]; + if (path[0] == '-') { + cmSystemTools::Error("No source directory specified for -S"); + return; + } + } + path = cmSystemTools::CollapseFullPath(path); cmSystemTools::ConvertToUnixSlashes(path); this->SetHomeDirectory(path); - } else if (arg.find("-S", 0) == 0) { - // There is no local generate anymore. Ignore -S option. } 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; + if (i >= args.size()) { + cmSystemTools::Error("No build directory specified for -B"); + return; + } + path = args[i]; + if (path[0] == '-') { + cmSystemTools::Error("No build directory specified for -B"); + return; + } + } + path = cmSystemTools::CollapseFullPath(path); cmSystemTools::ConvertToUnixSlashes(path); this->SetHomeOutputDirectory(path); @@ -835,20 +859,27 @@ void cmake::SetDirectoriesFromFile(const char* arg) this->SetHomeOutputDirectory(listPath); } else { // Source directory given on command line. Use current working - // directory as build tree. - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - this->SetHomeOutputDirectory(cwd); + // directory as build tree if -B hasn't been given already + if (this->GetHomeOutputDirectory().empty()) { + std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); + this->SetHomeOutputDirectory(cwd); + } } return; } - // We didn't find a CMakeLists.txt or CMakeCache.txt file from the - // argument. Assume it is the path to the source tree, and use the - // current working directory as the build tree. - std::string full = cmSystemTools::CollapseFullPath(arg); - std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); - this->SetHomeDirectory(full); - this->SetHomeOutputDirectory(cwd); + if (this->GetHomeDirectory().empty()) { + // We didn't find a CMakeLists.txt and it wasn't specified + // with -S. Assume it is the path to the source tree + std::string full = cmSystemTools::CollapseFullPath(arg); + this->SetHomeDirectory(full); + } + if (this->GetHomeOutputDirectory().empty()) { + // We didn't find a CMakeCache.txt and it wasn't specified + // with -B. Assume the current working directory as the build tree. + std::string cwd = cmSystemTools::GetCurrentWorkingDirectory(); + this->SetHomeOutputDirectory(cwd); + } } // at the end of this CMAKE_ROOT and CMAKE_COMMAND should be added to the diff --git a/Source/cmake.h b/Source/cmake.h index 4b4c67c..f7dc3f7 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -556,7 +556,9 @@ private: }; #define CMAKE_STANDARD_OPTIONS_TABLE \ - { "-C ", "Pre-load a script to populate the cache." }, \ + { "-S ", "Explicitly specify a source directory." }, \ + { "-B ", "Explicitly specify a build directory." }, \ + { "-C ", "Pre-load a script to populate the cache." }, \ { "-D [:]=", "Create or update a cmake cache entry." }, \ { "-U ", "Remove matching entries from CMake cache." }, \ { "-G ", "Specify a build system generator." }, \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index e3d94f6..75dabde 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -38,7 +38,8 @@ static const char* cmDocumentationName[][2] = { static const char* cmDocumentationUsage[][2] = { { nullptr, " cmake [options] \n" - " cmake [options] " }, + " cmake [options] \n" + " cmake [options] -S -B " }, { nullptr, "Specify a source directory to (re-)generate a build system for " "it in the current working directory. Specify an existing build " diff --git a/Tests/RunCMake/CommandLine/B-no-arg-result.txt b/Tests/RunCMake/CommandLine/B-no-arg-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/B-no-arg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/B-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/B-no-arg-stderr.txt new file mode 100644 index 0000000..2309c5e --- /dev/null +++ b/Tests/RunCMake/CommandLine/B-no-arg-stderr.txt @@ -0,0 +1 @@ +CMake Error: No build directory specified for -B diff --git a/Tests/RunCMake/CommandLine/B-no-arg2-result.txt b/Tests/RunCMake/CommandLine/B-no-arg2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/B-no-arg2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/B-no-arg2-stderr.txt b/Tests/RunCMake/CommandLine/B-no-arg2-stderr.txt new file mode 100644 index 0000000..2309c5e --- /dev/null +++ b/Tests/RunCMake/CommandLine/B-no-arg2-stderr.txt @@ -0,0 +1 @@ +CMake Error: No build directory specified for -B diff --git a/Tests/RunCMake/CommandLine/ExplicitDirs/CMakeLists.txt b/Tests/RunCMake/CommandLine/ExplicitDirs/CMakeLists.txt new file mode 100644 index 0000000..0ca5a0a --- /dev/null +++ b/Tests/RunCMake/CommandLine/ExplicitDirs/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) +add_custom_command( + OUTPUT output.txt + COMMAND ${CMAKE_COMMAND} -E echo CustomCommand > output.txt + ) +add_custom_target(CustomTarget ALL DEPENDS output.txt) +add_custom_target(CustomTarget2 ALL DEPENDS output.txt) +add_custom_target(CustomTarget3 ALL DEPENDS output.txt) diff --git a/Tests/RunCMake/CommandLine/NoArgs-stdout.txt b/Tests/RunCMake/CommandLine/NoArgs-stdout.txt index 1cd3469..f1dafc8 100644 --- a/Tests/RunCMake/CommandLine/NoArgs-stdout.txt +++ b/Tests/RunCMake/CommandLine/NoArgs-stdout.txt @@ -2,6 +2,7 @@ cmake \[options\] cmake \[options\] + cmake \[options\] -S -B Specify a source directory to \(re-\)generate a build system for it in the current working directory. Specify an existing build directory to diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index cef2b9b..e332336 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -48,6 +48,31 @@ run_cmake_command(cache-bad-entry run_cmake_command(cache-empty-entry ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-empty-entry/) +function(run_ExplicitDirs) + set(source_dir ${RunCMake_SOURCE_DIR}/ExplicitDirs) + set(binary_dir ${RunCMake_BINARY_DIR}/ExplicitDirs-build) + + file(REMOVE_RECURSE "${binary_dir}") + file(MAKE_DIRECTORY "${binary_dir}") + 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 ) + run_cmake_command(S-no-arg2 ${CMAKE_COMMAND} -S -T) + run_cmake_command(S-B ${CMAKE_COMMAND} -S ${source_dir} -B ${binary_dir}) + + # make sure that -B can explicitly construct build directories + file(REMOVE_RECURSE "${binary_dir}") + run_cmake_command(B-arg ${CMAKE_COMMAND} -B ${binary_dir} ${source_dir}) + file(REMOVE_RECURSE "${binary_dir}") + run_cmake_command(B-arg-reverse-order ${CMAKE_COMMAND} ${source_dir} -B${binary_dir}) + run_cmake_command(B-no-arg ${CMAKE_COMMAND} -B ) + run_cmake_command(B-no-arg2 ${CMAKE_COMMAND} -B -T) + file(REMOVE_RECURSE "${binary_dir}") + run_cmake_command(B-S ${CMAKE_COMMAND} -B${binary_dir} -S${source_dir}) + +endfunction() +run_ExplicitDirs() + function(run_BuildDir) # Use a single build tree for a few tests without cleaning. set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/BuildDir-build) diff --git a/Tests/RunCMake/CommandLine/S-no-arg-result.txt b/Tests/RunCMake/CommandLine/S-no-arg-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/S-no-arg-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/S-no-arg-stderr.txt b/Tests/RunCMake/CommandLine/S-no-arg-stderr.txt new file mode 100644 index 0000000..d1a2ce3 --- /dev/null +++ b/Tests/RunCMake/CommandLine/S-no-arg-stderr.txt @@ -0,0 +1 @@ +CMake Error: No source directory specified for -S diff --git a/Tests/RunCMake/CommandLine/S-no-arg2-result.txt b/Tests/RunCMake/CommandLine/S-no-arg2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/S-no-arg2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/S-no-arg2-stderr.txt b/Tests/RunCMake/CommandLine/S-no-arg2-stderr.txt new file mode 100644 index 0000000..d1a2ce3 --- /dev/null +++ b/Tests/RunCMake/CommandLine/S-no-arg2-stderr.txt @@ -0,0 +1 @@ +CMake Error: No source directory specified for -S -- cgit v0.12