From 73f23d1e0087a3b025ab7ba6b3e6195f19b40e1b Mon Sep 17 00:00:00 2001 From: Jiang Yi Date: Wed, 6 Mar 2019 20:49:51 +0800 Subject: cmake: add '--install ' option Fixes: #19023 --- Auxiliary/bash-completion/cmake | 2 +- Help/manual/cmake.1.rst | 42 ++++++- Help/release/dev/cmake--install_option.rst | 6 + Source/cmakemain.cxx | 125 +++++++++++++++++++++ Tests/RunCMake/CommandLine/RunCMakeTest.cmake | 8 ++ .../cmake_install.cmake | 15 +++ .../CommandLine/install-bad-dir-result.txt | 1 + .../CommandLine/install-bad-dir-stderr.txt | 1 + .../RunCMake/CommandLine/install-no-dir-result.txt | 1 + .../RunCMake/CommandLine/install-no-dir-stderr.txt | 1 + .../CommandLine/install-options-to-vars-result.txt | 1 + .../CommandLine/install-options-to-vars-stderr.txt | 4 + 12 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 Help/release/dev/cmake--install_option.rst create mode 100644 Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake create mode 100644 Tests/RunCMake/CommandLine/install-bad-dir-result.txt create mode 100644 Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/install-no-dir-result.txt create mode 100644 Tests/RunCMake/CommandLine/install-no-dir-stderr.txt create mode 100644 Tests/RunCMake/CommandLine/install-options-to-vars-result.txt create mode 100644 Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt diff --git a/Auxiliary/bash-completion/cmake b/Auxiliary/bash-completion/cmake index 5d67b0b..8c0c5e8 100644 --- a/Auxiliary/bash-completion/cmake +++ b/Auxiliary/bash-completion/cmake @@ -96,7 +96,7 @@ _cmake() _filedir return ;; - --build|--open) + --build|--install|--open) _filedir -d return ;; diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index e9a08b5..3ea6bc4 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -16,6 +16,9 @@ Synopsis `Build a Project`_ cmake --build [] [-- ] + `Install a Project`_ + cmake --install [] + `Open a Project`_ cmake --open @@ -39,8 +42,8 @@ buildsystem generator CMake. The above `Synopsis`_ lists various actions the tool can perform as described in sections below. To build a software project with CMake, `Generate a Project Buildsystem`_. -Optionally use **cmake** to `Build a Project`_ or just run the -corresponding build tool (e.g. ``make``) directly. **cmake** can also +Optionally use **cmake** to `Build a Project`_, `Install a Project`_ or just +run the corresponding build tool (e.g. ``make``) directly. **cmake** can also be used to `View Help`_. The other actions are meant for use by software developers writing @@ -302,6 +305,41 @@ following options: Run ``cmake --build`` with no options for quick help. +Install a Project +================= + +CMake provides a command-line signature to install an already-generated +project binary tree: + +.. code-block:: shell + + cmake --install [] + +This may be used after building a project to run installation without +using the generated build system or the native build tool. +The options are: + +``--install `` + Project binary directory to install. This is required and must be first. + +``--config `` + For multi-configuration tools, choose configuration ````. + +``--component `` + Component-based install. Only install component ````. + +``--prefix `` + The installation prefix CMAKE_INSTALL_PREFIX. + +``--strip`` + Strip before installing by setting CMAKE_INSTALL_DO_STRIP. + +``-v, --verbose`` + Enable verbose output. + + This option can be omitted if :envvar:`VERBOSE` environment variable is set. + +Run ``cmake --install`` with no options for quick help. Open a Project ============== diff --git a/Help/release/dev/cmake--install_option.rst b/Help/release/dev/cmake--install_option.rst new file mode 100644 index 0000000..8e526a0 --- /dev/null +++ b/Help/release/dev/cmake--install_option.rst @@ -0,0 +1,6 @@ +cmake--install-option +--------------------- + +* A new ``--install`` option was added to :manual:`cmake(1)`. + This may be used after building a project to run installation without + using the generated build system or the native build tool. diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 1c56bcd..d36ddf1 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -23,6 +23,7 @@ # include "cmsys/ConsoleBuf.hxx" #endif +#include #include #include #include @@ -71,11 +72,20 @@ static const char* cmDocumentationUsageNote[][2] = { " the build commands to be executed. \n" \ " -- = Pass remaining options to the native tool.\n" +# define CMAKE_INSTALL_OPTIONS \ + " = Project binary directory to install.\n" \ + " --config = For multi-configuration tools, choose .\n" \ + " --component = Component-based install. Only install .\n" \ + " --prefix = The installation prefix CMAKE_INSTALL_PREFIX.\n" \ + " --strip = Performing install/strip.\n" \ + " -v --verbose = Enable verbose output.\n" + static const char* cmDocumentationOptions[][2] = { CMAKE_STANDARD_OPTIONS_TABLE, { "-E", "CMake command mode." }, { "-L[A][H]", "List non-advanced cached variables." }, { "--build ", "Build a CMake-generated project binary tree." }, + { "--install ", "Install a CMake-generated project binary tree." }, { "--open ", "Open generated project in the associated application." }, { "-N", "View mode only." }, { "-P ", "Process script mode." }, @@ -114,6 +124,7 @@ static int do_command(int ac, char const* const* av) int do_cmake(int ac, char const* const* av); static int do_build(int ac, char const* const* av); +static int do_install(int ac, char const* const* av); static int do_open(int ac, char const* const* av); static cmMakefile* cmakemainGetMakefile(cmake* cm) @@ -188,6 +199,9 @@ int main(int ac, char const* const* av) if (strcmp(av[1], "--build") == 0) { return do_build(ac, av); } + if (strcmp(av[1], "--install") == 0) { + return do_install(ac, av); + } if (strcmp(av[1], "--open") == 0) { return do_open(ac, av); } @@ -523,6 +537,117 @@ static int do_build(int ac, char const* const* av) #endif } +static int do_install(int ac, char const* const* av) +{ +#ifndef CMAKE_BUILD_WITH_CMAKE + std::cerr << "This cmake does not support --install\n"; + return -1; +#else + assert(1 < ac); + + std::string config; + std::string component; + std::string prefix; + std::string dir; + bool strip = false; + bool verbose = cmSystemTools::HasEnv("VERBOSE"); + + enum Doing + { + DoingNone, + DoingDir, + DoingConfig, + DoingComponent, + DoingPrefix, + }; + + Doing doing = DoingDir; + + for (int i = 2; i < ac; ++i) { + if (strcmp(av[i], "--config") == 0) { + doing = DoingConfig; + } else if (strcmp(av[i], "--component") == 0) { + doing = DoingComponent; + } else if (strcmp(av[i], "--prefix") == 0) { + doing = DoingPrefix; + } else if (strcmp(av[i], "--strip") == 0) { + strip = true; + doing = DoingNone; + } else if ((strcmp(av[i], "--verbose") == 0) || + (strcmp(av[i], "-v") == 0)) { + verbose = true; + doing = DoingNone; + } else { + switch (doing) { + case DoingDir: + dir = cmSystemTools::CollapseFullPath(av[i]); + doing = DoingNone; + break; + case DoingConfig: + config = av[i]; + doing = DoingNone; + break; + case DoingComponent: + component = av[i]; + doing = DoingNone; + break; + case DoingPrefix: + prefix = av[i]; + doing = DoingNone; + break; + default: + std::cerr << "Unknown argument " << av[i] << std::endl; + dir.clear(); + break; + } + } + } + + if (dir.empty()) { + std::cerr << "Usage: cmake --install " + "[options]\nOptions:\n" CMAKE_INSTALL_OPTIONS; + return 1; + } + + cmake cm(cmake::RoleScript, cmState::Script); + + cmSystemTools::SetMessageCallback( + [&cm](const std::string& msg, const char* title) { + cmakemainMessageCallback(msg, title, &cm); + }); + cm.SetProgressCallback([&cm](const std::string& msg, float prog) { + cmakemainProgressCallback(msg, prog, &cm); + }); + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); + cm.SetDebugOutputOn(verbose); + cm.SetWorkingMode(cmake::SCRIPT_MODE); + + std::vector args{ av[0] }; + + if (!prefix.empty()) { + args.emplace_back("-DCMAKE_INSTALL_PREFIX=" + prefix); + } + + if (!component.empty()) { + args.emplace_back("-DCMAKE_INSTALL_COMPONENT=" + component); + } + + if (strip) { + args.emplace_back("-DCMAKE_INSTALL_DO_STRIP=1"); + } + + if (!config.empty()) { + args.emplace_back("-DCMAKE_INSTALL_CONFIG_NAME=" + config); + } + + args.emplace_back("-P"); + args.emplace_back(dir + "/cmake_install.cmake"); + + return cm.Run(args) ? 1 : 0; +#endif +} + static int do_open(int ac, char const* const* av) { #ifndef CMAKE_BUILD_WITH_CMAKE diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index ff2a8a5..066e9b8 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -54,6 +54,14 @@ run_cmake_command(build-bad-dir run_cmake_command(build-bad-generator ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-generator) +run_cmake_command(install-no-dir + ${CMAKE_COMMAND} --install) +run_cmake_command(install-bad-dir + ${CMAKE_COMMAND} --install dir-does-not-exist) +run_cmake_command(install-options-to-vars + ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars + --strip --prefix /var/test --config sample --component pack) + run_cmake_command(cache-bad-entry ${CMAKE_COMMAND} --build ${RunCMake_SOURCE_DIR}/cache-bad-entry/) run_cmake_command(cache-empty-entry diff --git a/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake b/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake new file mode 100644 index 0000000..fd4e67d --- /dev/null +++ b/Tests/RunCMake/CommandLine/dir-install-options-to-vars/cmake_install.cmake @@ -0,0 +1,15 @@ +if(CMAKE_INSTALL_PREFIX) + message("CMAKE_INSTALL_PREFIX is ${CMAKE_INSTALL_PREFIX}") +endif() + +if(CMAKE_INSTALL_COMPONENT) + message("CMAKE_INSTALL_COMPONENT is ${CMAKE_INSTALL_COMPONENT}") +endif() + +if(CMAKE_INSTALL_CONFIG_NAME) + message("CMAKE_INSTALL_CONFIG_NAME is ${CMAKE_INSTALL_CONFIG_NAME}") +endif() + +if(CMAKE_INSTALL_DO_STRIP) + message("CMAKE_INSTALL_DO_STRIP is ${CMAKE_INSTALL_DO_STRIP}") +endif() diff --git a/Tests/RunCMake/CommandLine/install-bad-dir-result.txt b/Tests/RunCMake/CommandLine/install-bad-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-bad-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt b/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt new file mode 100644 index 0000000..320aecc --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-bad-dir-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Error processing file: diff --git a/Tests/RunCMake/CommandLine/install-no-dir-result.txt b/Tests/RunCMake/CommandLine/install-no-dir-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-no-dir-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt b/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt new file mode 100644 index 0000000..d64f638 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-no-dir-stderr.txt @@ -0,0 +1 @@ +^Usage: cmake --install \[options\] diff --git a/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt b/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt new file mode 100644 index 0000000..573541a --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-options-to-vars-result.txt @@ -0,0 +1 @@ +0 diff --git a/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt b/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt new file mode 100644 index 0000000..f7b1583 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-options-to-vars-stderr.txt @@ -0,0 +1,4 @@ +CMAKE_INSTALL_PREFIX is /var/test +CMAKE_INSTALL_COMPONENT is pack +CMAKE_INSTALL_CONFIG_NAME is sample +CMAKE_INSTALL_DO_STRIP is 1 -- cgit v0.12