diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index 2d632e7dbe..1449f3483c 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -1791,10 +1791,11 @@ bool HandleDirectoryMode(std::vector const& args, exclude_from_all = true; doing = DoingNone; } else if (doing == DoingDirs) { - // Convert this directory to a full path. + // If the given directory is not a full path, convert it to one by + // assuming it's relative to the current source directory. std::string dir = args[i]; std::string::size_type gpos = cmGeneratorExpression::Find(dir); - if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) { + if (!dir.empty() && gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) { dir = cmStrCat(helper.Makefile->GetCurrentSourceDirectory(), '/', args[i]); } diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx index a388d917d8..cf1fac91fc 100644 --- a/Source/cmInstallDirectoryGenerator.cxx +++ b/Source/cmInstallDirectoryGenerator.cxx @@ -2,6 +2,7 @@ file LICENSE.rst or https://cmake.org/licensing for details. */ #include "cmInstallDirectoryGenerator.h" +#include #include #include "cmGeneratorExpression.h" @@ -54,6 +55,13 @@ bool cmInstallDirectoryGenerator::Compute(cmLocalGenerator* lg) std::vector cmInstallDirectoryGenerator::GetDirectories( std::string const& config) const { + // If given only empty directories, collapse into a single specification to + // avoid redundant calls. This supports the use case of installing an empty + // directory into a destination when a directory is not specified. + if (std::all_of(this->Directories.begin(), this->Directories.end(), + [](std::string const& d) { return d.empty(); })) { + return std::vector{ "" }; + } cmList directories; if (this->ActionsPerConfig) { for (std::string const& f : this->Directories) { @@ -81,11 +89,13 @@ void cmInstallDirectoryGenerator::GenerateScriptForConfig( { std::vector dirs = this->GetDirectories(config); - // Make sure all dirs have absolute paths. - cmMakefile const& mf = *this->LocalGenerator->GetMakefile(); - for (std::string& d : dirs) { - if (!cmSystemTools::FileIsFullPath(d)) { - d = cmStrCat(mf.GetCurrentSourceDirectory(), '/', d); + if (!(dirs.size() == 1 && dirs[0].empty())) { + // Make sure all dirs have absolute paths. + cmMakefile const& mf = *this->LocalGenerator->GetMakefile(); + for (std::string& d : dirs) { + if (!cmSystemTools::FileIsFullPath(d)) { + d = cmStrCat(mf.GetCurrentSourceDirectory(), '/', d); + } } } diff --git a/Tests/RunCMake/install/DIRECTORY-PATTERN-all-check.cmake b/Tests/RunCMake/install/DIRECTORY-PATTERN-all-check.cmake index 7a20edc364..504d1fde35 100644 --- a/Tests/RunCMake/install/DIRECTORY-PATTERN-all-check.cmake +++ b/Tests/RunCMake/install/DIRECTORY-PATTERN-all-check.cmake @@ -1 +1 @@ -check_installed([[^dir1;dir1/empty\.c;dir1/empty\.h;dir2;dir2/pattern;dir2/pattern/empty\.txt;dir3;dir3/empty\.c;dir3/empty\.h;dir3/empty\.txt;dir4;dir4/empty\.c;dir4/empty\.h;dir4/empty\.txt;empty$]]) +check_installed([[^dir1;dir1/empty\.c;dir1/empty\.h;dir2;dir2/pattern;dir2/pattern/empty\.txt;dir3;dir3/empty\.c;dir3/empty\.h;dir3/empty\.txt;dir4;dir4/empty\.c;dir4/empty\.h;dir4/empty\.txt;empty;empty_str;empty_with_genex$]]) diff --git a/Tests/RunCMake/install/DIRECTORY-PATTERN.cmake b/Tests/RunCMake/install/DIRECTORY-PATTERN.cmake index 74d804351e..61007ac44f 100644 --- a/Tests/RunCMake/install/DIRECTORY-PATTERN.cmake +++ b/Tests/RunCMake/install/DIRECTORY-PATTERN.cmake @@ -34,3 +34,13 @@ install( DIRECTORY DESTINATION empty ) + +install( + DIRECTORY "" "" + DESTINATION empty_str + ) + +install( + DIRECTORY + DESTINATION $ + )