diff --git a/Help/command/install.rst b/Help/command/install.rst index c99ed7361..9c17bbaef 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -192,6 +192,10 @@ The list of ``files...`` given to ``FILES`` or ``PROGRAMS`` may use However, if any item begins in a generator expression it must evaluate to a full path. +The install destination given to the files install ``DESTINATION`` may +use "generator expressions" with the syntax ``$<...>``. See the +:manual:`cmake-generator-expressions(7)` manual for available expressions. + Installing Directories ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Help/release/dev/install-files-dest-genex.rst b/Help/release/dev/install-files-dest-genex.rst new file mode 100644 index 000000000..b7aa8b3be --- /dev/null +++ b/Help/release/dev/install-files-dest-genex.rst @@ -0,0 +1,5 @@ +install-files-dest-genex +------------------------ + +* The :command:`install(FILES)` command ``DESTINATION`` option learned to + support :manual:`generator expressions `. diff --git a/Source/cmInstallFilesGenerator.cxx b/Source/cmInstallFilesGenerator.cxx index c18b174b4..e2c16c8f5 100644 --- a/Source/cmInstallFilesGenerator.cxx +++ b/Source/cmInstallFilesGenerator.cxx @@ -34,6 +34,12 @@ cmInstallFilesGenerator Programs(programs), Optional(optional) { + // We need per-config actions if the destination has generator expressions. + if(cmGeneratorExpression::Find(Destination) != std::string::npos) + { + this->ActionsPerConfig = true; + } + // We need per-config actions if any files have generator expressions. for(std::vector::const_iterator i = files.begin(); !this->ActionsPerConfig && i != files.end(); ++i) @@ -56,15 +62,26 @@ void cmInstallFilesGenerator::Compute(cmLocalGenerator* lg) this->LocalGenerator = lg; } +//---------------------------------------------------------------------------- +std::string +cmInstallFilesGenerator::GetDestination(std::string const& config) const +{ + cmGeneratorExpression ge; + return ge.Parse(this->Destination) + ->Evaluate(this->LocalGenerator->GetMakefile(), config); +} + //---------------------------------------------------------------------------- void cmInstallFilesGenerator::AddFilesInstallRule( - std::ostream& os, Indent const& indent, + std::ostream& os, + const std::string config, + Indent const& indent, std::vector const& files) { // Write code to install the files. const char* no_dir_permissions = 0; this->AddInstallRule(os, - this->Destination, + this->GetDestination(config), (this->Programs ? cmInstallType_PROGRAMS : cmInstallType_FILES), @@ -84,7 +101,7 @@ void cmInstallFilesGenerator::GenerateScriptActions(std::ostream& os, } else { - this->AddFilesInstallRule(os, indent, this->Files); + this->AddFilesInstallRule(os, "", indent, this->Files); } } @@ -102,5 +119,5 @@ void cmInstallFilesGenerator::GenerateScriptForConfig(std::ostream& os, cmSystemTools::ExpandListArgument(cge->Evaluate( this->LocalGenerator->GetMakefile(), config), files); } - this->AddFilesInstallRule(os, indent, files); + this->AddFilesInstallRule(os, config, indent, files); } diff --git a/Source/cmInstallFilesGenerator.h b/Source/cmInstallFilesGenerator.h index 00b3a7939..bfe403924 100644 --- a/Source/cmInstallFilesGenerator.h +++ b/Source/cmInstallFilesGenerator.h @@ -32,12 +32,16 @@ public: void Compute(cmLocalGenerator* lg); + std::string GetDestination(std::string const& config) const; + protected: virtual void GenerateScriptActions(std::ostream& os, Indent const& indent); virtual void GenerateScriptForConfig(std::ostream& os, const std::string& config, Indent const& indent); - void AddFilesInstallRule(std::ostream& os, Indent const& indent, + void AddFilesInstallRule(std::ostream& os, + const std::string config, + Indent const& indent, std::vector const& files); cmLocalGenerator* LocalGenerator; diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 2b9e8442c..1e52a0945 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -29,14 +29,14 @@ add_custom_command(TARGET testLib1 POST_BUILD $.genex ) install(FILES $.genex - DESTINATION lib + DESTINATION $<1:lib>$<0:/wrong> ) set_property(TARGET testLib1 PROPERTY MY_FILES ${CMAKE_CURRENT_SOURCE_DIR}/testLib1file1.txt ${CMAKE_CURRENT_SOURCE_DIR}/testLib1file2.txt ) install(FILES $ - DESTINATION doc + DESTINATION $<1:doc>$<0:/wrong> ) # Test library with empty link interface. Link it to an implementation diff --git a/Tests/RunCMake/install/FILES-DESTINATION-bad-result.txt b/Tests/RunCMake/install/FILES-DESTINATION-bad-result.txt new file mode 100644 index 000000000..d00491fd7 --- /dev/null +++ b/Tests/RunCMake/install/FILES-DESTINATION-bad-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/install/FILES-DESTINATION-bad-stderr.txt b/Tests/RunCMake/install/FILES-DESTINATION-bad-stderr.txt new file mode 100644 index 000000000..984415868 --- /dev/null +++ b/Tests/RunCMake/install/FILES-DESTINATION-bad-stderr.txt @@ -0,0 +1,6 @@ +CMake Error: + Error evaluating generator expression: + + \$ + + Expression did not evaluate to a known generator expression diff --git a/Tests/RunCMake/install/FILES-DESTINATION-bad.cmake b/Tests/RunCMake/install/FILES-DESTINATION-bad.cmake new file mode 100644 index 000000000..0fda078db --- /dev/null +++ b/Tests/RunCMake/install/FILES-DESTINATION-bad.cmake @@ -0,0 +1 @@ +install(FILES empty.c DESTINATION $) diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index a5f5bd0ec..2ce009551 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -6,6 +6,7 @@ run_cmake(DIRECTORY-message-lazy) run_cmake(SkipInstallRulesWarning) run_cmake(SkipInstallRulesNoWarning1) run_cmake(SkipInstallRulesNoWarning2) +run_cmake(FILES-DESTINATION-bad) run_cmake(TARGETS-DESTINATION-bad) run_cmake(CMP0062-OLD) run_cmake(CMP0062-NEW) diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt index cc3c3be61..3227e3ffa 100644 --- a/Tests/SimpleInstall/CMakeLists.txt +++ b/Tests/SimpleInstall/CMakeLists.txt @@ -209,9 +209,9 @@ else() ARCHIVE DESTINATION MyTest/lib/static OPTIONAL # for coverage...target should always exist ) - install(FILES lib1.h DESTINATION MyTest/include/foo) + install(FILES lib1.h DESTINATION MyTest/include/$<1:foo>$<0:/wrong>) install(FILES lib2.h - DESTINATION MyTest/include/foo + DESTINATION $<1:MyTest/include/foo>$<0:/wrong> COMPONENT Development PERMISSIONS OWNER_READ OWNER_WRITE RENAME lib2renamed.h diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt index cc3c3be61..3227e3ffa 100644 --- a/Tests/SimpleInstallS2/CMakeLists.txt +++ b/Tests/SimpleInstallS2/CMakeLists.txt @@ -209,9 +209,9 @@ else() ARCHIVE DESTINATION MyTest/lib/static OPTIONAL # for coverage...target should always exist ) - install(FILES lib1.h DESTINATION MyTest/include/foo) + install(FILES lib1.h DESTINATION MyTest/include/$<1:foo>$<0:/wrong>) install(FILES lib2.h - DESTINATION MyTest/include/foo + DESTINATION $<1:MyTest/include/foo>$<0:/wrong> COMPONENT Development PERMISSIONS OWNER_READ OWNER_WRITE RENAME lib2renamed.h