diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 4bf2929fa5..1983168810 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -917,6 +917,13 @@ The options are: Component-based install. Only install component ````. + .. versionadded:: 4.4 + + Supports installing more than one component: + + * ``--component `` + * ``--component --component `` + .. option:: --default-directory-permissions Default directory install permissions. Permissions in format ````. diff --git a/Help/release/dev/cmake-install-multi-component.rst b/Help/release/dev/cmake-install-multi-component.rst new file mode 100644 index 0000000000..0e3d3aac33 --- /dev/null +++ b/Help/release/dev/cmake-install-multi-component.rst @@ -0,0 +1,5 @@ +cmake-install-multi-component +----------------------------- + +* The :option:`cmake --install` command now supports installing + multiple components. diff --git a/Source/cmInstallScriptHandler.cxx b/Source/cmInstallScriptHandler.cxx index 12f72568db..6a268f9e4c 100644 --- a/Source/cmInstallScriptHandler.cxx +++ b/Source/cmInstallScriptHandler.cxx @@ -33,24 +33,27 @@ using InstallScript = cmInstallScriptHandler::InstallScript; using InstallScriptRunner = cmInstallScriptHandler::InstallScriptRunner; -cmInstallScriptHandler::cmInstallScriptHandler(std::string _binaryDir, - std::string _component, - std::string _config, - std::vector& args) - : binaryDir(std::move(_binaryDir)) - , component(std::move(_component)) +cmInstallScriptHandler::cmInstallScriptHandler( + std::string _binaryDir, std::vector _components, + std::string _config, std::vector& args) + : components(std::move(_components)) + , binaryDir(std::move(_binaryDir)) { + if (this->components.empty()) { + this->components.emplace_back(std::string{}); + } + std::string const& file = cmStrCat(this->binaryDir, "/CMakeFiles/InstallScripts.json"); this->parallel = false; - auto addScript = [this, &args](std::string script, + auto addScript = [this, &args](std::string script, std::string component, std::string config) -> void { this->scripts.push_back({ script, config, args }); - if (!this->component.empty()) { + if (!component.empty()) { this->scripts.back().command.insert( this->scripts.back().command.end() - 1, - cmStrCat("-DCMAKE_INSTALL_COMPONENT=", this->component)); + cmStrCat("-DCMAKE_INSTALL_COMPONENT=", component)); } if (!config.empty()) { this->scripts.back().command.insert( @@ -86,15 +89,20 @@ cmInstallScriptHandler::cmInstallScriptHandler(std::string _binaryDir, this->configs.push_back(_config); } for (auto const& script : value["InstallScripts"]) { - for (auto const& config : configs) { - addScript(script.asCString(), config); + for (auto const& component : components) { + for (auto const& config : configs) { + addScript(script.asCString(), component, config); + } } if (!this->parallel) { break; } } } else { - addScript(cmStrCat(this->binaryDir, "/cmake_install.cmake"), _config); + for (auto const& component : components) { + addScript(cmStrCat(this->binaryDir, "/cmake_install.cmake"), component, + _config); + } } } @@ -161,30 +169,31 @@ int cmInstallScriptHandler::Install(unsigned int j, // Write install manifest std::string install_manifest; - if (this->component.empty()) { - install_manifest = "install_manifest.txt"; - } else { - cmsys::RegularExpression regEntry; - if (regEntry.compile("^[a-zA-Z0-9_.+-]+$") && - regEntry.find(this->component)) { - install_manifest = - cmStrCat("install_manifest_", this->component, ".txt"); + for (auto const& component : this->components) { + if (component.empty()) { + install_manifest = "install_manifest.txt"; } else { - cmCryptoHash md5(cmCryptoHash::AlgoMD5); - md5.Initialize(); - install_manifest = - cmStrCat("install_manifest_", md5.HashString(this->component), ".txt"); + cmsys::RegularExpression regEntry; + if (regEntry.compile("^[a-zA-Z0-9_.+-]+$") && regEntry.find(component)) { + install_manifest = cmStrCat("install_manifest_", component, ".txt"); + } else { + cmCryptoHash md5(cmCryptoHash::AlgoMD5); + md5.Initialize(); + install_manifest = + cmStrCat("install_manifest_", md5.HashString(component), ".txt"); + } } - } - cmGeneratedFileStream fout(cmStrCat(this->binaryDir, '/', install_manifest)); - fout.SetCopyIfDifferent(true); - for (auto const& dir : this->directories) { - auto local_manifest = cmStrCat(dir, "/install_local_manifest.txt"); - if (cmSystemTools::FileExists(local_manifest)) { - cmsys::ifstream fin(local_manifest.c_str()); - std::string line; - while (std::getline(fin, line)) { - fout << line << "\n"; + cmGeneratedFileStream fout( + cmStrCat(this->binaryDir, '/', install_manifest)); + fout.SetCopyIfDifferent(true); + for (auto const& dir : this->directories) { + auto local_manifest = cmStrCat(dir, "/install_local_manifest.txt"); + if (cmSystemTools::FileExists(local_manifest)) { + cmsys::ifstream fin(local_manifest.c_str()); + std::string line; + while (std::getline(fin, line)) { + fout << line << "\n"; + } } } } diff --git a/Source/cmInstallScriptHandler.h b/Source/cmInstallScriptHandler.h index 6f2a7d7f34..3fcfac0e37 100644 --- a/Source/cmInstallScriptHandler.h +++ b/Source/cmInstallScriptHandler.h @@ -21,7 +21,7 @@ class cmInstallScriptHandler { public: cmInstallScriptHandler() = default; - cmInstallScriptHandler(std::string, std::string, std::string, + cmInstallScriptHandler(std::string, std::vector, std::string, std::vector&); bool IsParallel(); int Install(unsigned int j, cmInstrumentation& instrumentation); @@ -51,7 +51,7 @@ private: std::vector scripts; std::vector configs; std::vector directories; + std::vector components; std::string binaryDir; - std::string component; bool parallel; }; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index b42028b0d6..bb943f549d 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -801,7 +801,7 @@ int do_install(int ac, char const* const* av) assert(1 < ac); std::string config; - std::string component; + std::vector components; std::string defaultDirectoryPermissions; std::string prefix; std::string dir; @@ -809,6 +809,17 @@ int do_install(int ac, char const* const* av) bool strip = false; bool verbose = cmSystemTools::HasEnv("VERBOSE"); + auto componentLambda = [&components](std::string const& value) -> bool { + if (!value.empty()) { + cmList values{ value }; + for (auto const& v : values) { + components.emplace_back(v); + } + return true; + } + return false; + }; + auto jLambda = extract_job_number_lambda_builder(dir, jobs, "-j"); auto parallelLambda = extract_job_number_lambda_builder(dir, jobs, "--parallel"); @@ -824,8 +835,8 @@ int do_install(int ac, char const* const* av) std::vector arguments = { CommandArgument{ "--config", CommandArgument::Values::One, CommandArgument::setToValue(config) }, - CommandArgument{ "--component", CommandArgument::Values::One, - CommandArgument::setToValue(component) }, + CommandArgument{ "--component", CommandArgument::Values::OneOrMore, + componentLambda }, CommandArgument{ "--default-directory-permissions", CommandArgument::Values::One, CommandArgument::setToValue(defaultDirectoryPermissions) }, @@ -876,6 +887,7 @@ int do_install(int ac, char const* const* av) " = Project binary directory to install.\n" " --config = For multi-configuration tools, choose .\n" " --component = Component-based install. Only install .\n" + " May be passed multiple components. t\n" " --default-directory-permissions \n" " Default install permission. Use default permission .\n" " -j --parallel \n" @@ -915,7 +927,7 @@ int do_install(int ac, char const* const* av) args.emplace_back("-P"); cmInstrumentation instrumentation(dir); - auto handler = cmInstallScriptHandler(dir, component, config, args); + auto handler = cmInstallScriptHandler(dir, components, config, args); int ret = 0; if (!jobs && handler.IsParallel()) { jobs = 1; diff --git a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake index ec72bcdce7..6ceedfa187 100644 --- a/Tests/RunCMake/CommandLine/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLine/RunCMakeTest.cmake @@ -147,6 +147,15 @@ run_cmake_command(install-unknown-command-long 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(install-no-component-value + ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars + --component) +run_cmake_command(install-multi-component-1 + ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars + --component comp1 comp2) +run_cmake_command(install-multi-component-2 + ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-install-options-to-vars + --component comp1 --component comp2) run_cmake_command(install-default-dir-permissions-all ${CMAKE_COMMAND} --install ${RunCMake_SOURCE_DIR}/dir-permissions-install-options-to-vars --default-directory-permissions u=rwx,g=rx,o=rx) diff --git a/Tests/RunCMake/CommandLine/install-multi-component-1-stderr.txt b/Tests/RunCMake/CommandLine/install-multi-component-1-stderr.txt new file mode 100644 index 0000000000..4abd24ee53 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-multi-component-1-stderr.txt @@ -0,0 +1,2 @@ +CMAKE_INSTALL_COMPONENT is comp1 +CMAKE_INSTALL_COMPONENT is comp2 diff --git a/Tests/RunCMake/CommandLine/install-multi-component-2-stderr.txt b/Tests/RunCMake/CommandLine/install-multi-component-2-stderr.txt new file mode 100644 index 0000000000..4abd24ee53 --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-multi-component-2-stderr.txt @@ -0,0 +1,2 @@ +CMAKE_INSTALL_COMPONENT is comp1 +CMAKE_INSTALL_COMPONENT is comp2 diff --git a/Tests/RunCMake/CommandLine/install-no-component-value-result.txt b/Tests/RunCMake/CommandLine/install-no-component-value-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-no-component-value-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/CommandLine/install-no-component-value-stderr.txt b/Tests/RunCMake/CommandLine/install-no-component-value-stderr.txt new file mode 100644 index 0000000000..a8eff7c47c --- /dev/null +++ b/Tests/RunCMake/CommandLine/install-no-component-value-stderr.txt @@ -0,0 +1 @@ +^CMake Error: Invalid value used with --component