diff options
author | Jon Chronopoulos <patches@crondog.com> | 2018-11-29 21:11:07 +1100 |
---|---|---|
committer | Craig Scott <craig.scott@crascit.com> | 2018-12-23 09:03:38 +1100 |
commit | 25cae1e85d501c463141388e4eb580bdfae6ed2f (patch) | |
tree | 5028fc6c22c526e2b67a4539b6d0a7b69747b17a | |
parent | cb995ddea2d633310b270e99d020fe490fff5ec7 (diff) | |
download | cmake-25cae1e85d501c463141388e4eb580bdfae6ed2f.tar.gz |
install: Teach CODE,SCRIPT modes to evaluate generator expressions
This also introduces CMP0087 which will keep the OLD behaviour of not
evaluating generator expressions
Fixes: #15785
-rw-r--r-- | Help/command/install.rst | 5 | ||||
-rw-r--r-- | Help/manual/cmake-policies.7.rst | 1 | ||||
-rw-r--r-- | Help/policy/CMP0087.rst | 29 | ||||
-rw-r--r-- | Help/release/dev/install-code-script-genex.rst | 5 | ||||
-rw-r--r-- | Source/cmInstallScriptGenerator.cxx | 70 | ||||
-rw-r--r-- | Source/cmInstallScriptGenerator.h | 14 | ||||
-rw-r--r-- | Source/cmPolicies.h | 6 | ||||
-rw-r--r-- | Tests/RunCMake/install/CMP0087-NEW-check.cmake | 7 | ||||
-rw-r--r-- | Tests/RunCMake/install/CMP0087-NEW.cmake | 3 | ||||
-rw-r--r-- | Tests/RunCMake/install/CMP0087-NEW/CMakeLists.txt | 7 | ||||
-rw-r--r-- | Tests/RunCMake/install/CMP0087-OLD-check.cmake | 8 | ||||
-rw-r--r-- | Tests/RunCMake/install/CMP0087-OLD.cmake | 3 | ||||
-rw-r--r-- | Tests/RunCMake/install/CMP0087-OLD/CMakeLists.txt | 6 | ||||
-rw-r--r-- | Tests/RunCMake/install/CMP0087-WARN-stderr.txt | 5 | ||||
-rw-r--r-- | Tests/RunCMake/install/CMP0087-WARN.cmake | 2 | ||||
-rw-r--r-- | Tests/RunCMake/install/RunCMakeTest.cmake | 3 |
16 files changed, 162 insertions, 12 deletions
diff --git a/Help/command/install.rst b/Help/command/install.rst index 55c8485ae1..a0e8c37684 100644 --- a/Help/command/install.rst +++ b/Help/command/install.rst @@ -547,6 +547,11 @@ example, the code will print a message during installation. +``<file>`` or ``<code>`` may use "generator expressions" with the syntax +``$<...>`` (in the case of ``<file>``, this refers to their use in the file +name, not the file's contents). See the +:manual:`cmake-generator-expressions(7)` manual for available expressions. + Installing Exports ^^^^^^^^^^^^^^^^^^ diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index ed61ae042b..40ec1ef987 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.14 .. toctree:: :maxdepth: 1 + CMP0087: install(SCRIPT | CODE) supports generator expressions. </policy/CMP0087> CMP0086: UseSWIG honors SWIG_MODULE_NAME via -module flag. </policy/CMP0086> CMP0085: IN_LIST generator expression handles empty list items. </policy/CMP0085> CMP0084: The FindQt module does not exist for find_package(). </policy/CMP0084> diff --git a/Help/policy/CMP0087.rst b/Help/policy/CMP0087.rst new file mode 100644 index 0000000000..4c45b99e4c --- /dev/null +++ b/Help/policy/CMP0087.rst @@ -0,0 +1,29 @@ +CMP0087 +------- + +:command:`install(CODE)` and :command:`install(SCRIPT)` support generator +expressions. + +In CMake 3.13 and earlier, :command:`install(CODE)` and +:command:`install(SCRIPT)` did not evaluate generator expressions. CMake 3.14 +and later will evaluate generator expressions for :command:`install(CODE)` and +:command:`install(SCRIPT)`. + +The ``OLD`` behavior of this policy is for :command:`install(CODE)` and +:command:`install(SCRIPT)` to not evaluate generator expressions. The ``NEW`` +behavior is to evaluate generator expressions for :command:`install(CODE)` and +:command:`install(SCRIPT)`. + +Note that it is the value of this policy setting at the end of the directory +scope that is important, not its setting at the time of the call to +:command:`install(CODE)` or :command:`install(SCRIPT)`. This has implications +for calling these commands from places that have their own policy scope but not +their own directory scope (e.g. from files brought in via :command:`include()` +rather than :command:`add_subdirectory()`). + +This policy was introduced in CMake version 3.14. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/install-code-script-genex.rst b/Help/release/dev/install-code-script-genex.rst new file mode 100644 index 0000000000..a28a46667c --- /dev/null +++ b/Help/release/dev/install-code-script-genex.rst @@ -0,0 +1,5 @@ +install-code-script-genex +------------------------- + +* The :command:`install(CODE)` and :command:`install(SCRIPT)` commands + learned to support generator expressions. See policy :policy:`CMP0087`. diff --git a/Source/cmInstallScriptGenerator.cxx b/Source/cmInstallScriptGenerator.cxx index 7d77b7c9e2..b93debbb4e 100644 --- a/Source/cmInstallScriptGenerator.cxx +++ b/Source/cmInstallScriptGenerator.cxx @@ -2,11 +2,15 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmInstallScriptGenerator.h" -#include "cmScriptGenerator.h" - #include <ostream> #include <vector> +#include "cmGeneratorExpression.h" +#include "cmLocalGenerator.h" +#include "cmPolicies.h" +#include "cmScriptGenerator.h" +#include "cmake.h" + cmInstallScriptGenerator::cmInstallScriptGenerator(const char* script, bool code, const char* component, @@ -15,25 +19,71 @@ cmInstallScriptGenerator::cmInstallScriptGenerator(const char* script, MessageDefault, exclude_from_all) , Script(script) , Code(code) + , AllowGenex(false) { + // We need per-config actions if the script has generator expressions. + if (cmGeneratorExpression::Find(Script) != std::string::npos) { + this->ActionsPerConfig = true; + } } cmInstallScriptGenerator::~cmInstallScriptGenerator() { } -void cmInstallScriptGenerator::GenerateScript(std::ostream& os) +void cmInstallScriptGenerator::Compute(cmLocalGenerator* lg) { - Indent indent; - std::string component_test = - this->CreateComponentTest(this->Component.c_str(), this->ExcludeFromAll); - os << indent << "if(" << component_test << ")\n"; + this->LocalGenerator = lg; + if (this->ActionsPerConfig) { + switch (this->LocalGenerator->GetPolicyStatus(cmPolicies::CMP0087)) { + case cmPolicies::WARN: + this->LocalGenerator->IssueMessage( + cmake::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0087)); + CM_FALLTHROUGH; + case cmPolicies::OLD: + break; + case cmPolicies::NEW: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + this->AllowGenex = true; + break; + } + } +} + +void cmInstallScriptGenerator::AddScriptInstallRule(std::ostream& os, + Indent indent, + std::string const& script) +{ if (this->Code) { - os << indent << this->Script << "\n"; + os << indent << script << "\n"; } else { - os << indent << "include(\"" << this->Script << "\")\n"; + os << indent << "include(\"" << script << "\")\n"; } +} - os << indent << "endif()\n\n"; +void cmInstallScriptGenerator::GenerateScriptActions(std::ostream& os, + Indent indent) +{ + if (this->AllowGenex && this->ActionsPerConfig) { + this->cmInstallGenerator::GenerateScriptActions(os, indent); + } else { + this->AddScriptInstallRule(os, indent, this->Script); + } +} + +void cmInstallScriptGenerator::GenerateScriptForConfig( + std::ostream& os, const std::string& config, Indent indent) +{ + if (this->AllowGenex) { + cmGeneratorExpression ge; + std::unique_ptr<cmCompiledGeneratorExpression> cge = + ge.Parse(this->Script); + this->AddScriptInstallRule(os, indent, + cge->Evaluate(this->LocalGenerator, config)); + } else { + this->AddScriptInstallRule(os, indent, this->Script); + } } diff --git a/Source/cmInstallScriptGenerator.h b/Source/cmInstallScriptGenerator.h index fe0f7c6f11..05199d7907 100644 --- a/Source/cmInstallScriptGenerator.h +++ b/Source/cmInstallScriptGenerator.h @@ -6,10 +6,13 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmInstallGenerator.h" +#include "cmScriptGenerator.h" #include <iosfwd> #include <string> +class cmLocalGenerator; + /** \class cmInstallScriptGenerator * \brief Generate target installation rules. */ @@ -20,10 +23,19 @@ public: const char* component, bool exclude_from_all); ~cmInstallScriptGenerator() override; + void Compute(cmLocalGenerator* lg) override; + protected: - void GenerateScript(std::ostream& os) override; + void GenerateScriptActions(std::ostream& os, Indent indent) override; + void GenerateScriptForConfig(std::ostream& os, const std::string& config, + Indent indent) override; + void AddScriptInstallRule(std::ostream& os, Indent indent, + std::string const& script); + std::string Script; bool Code; + cmLocalGenerator* LocalGenerator; + bool AllowGenex; }; #endif diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 7674877362..206dd3da2e 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -254,7 +254,11 @@ class cmMakefile; 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0086, \ "UseSWIG honors SWIG_MODULE_NAME via -module flag.", 3, 14, 0, \ - cmPolicies::WARN) + cmPolicies::WARN) \ + SELECT(POLICY, CMP0087, \ + "Install CODE|SCRIPT allow the use of generator " \ + "expressions.", \ + 3, 14, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/install/CMP0087-NEW-check.cmake b/Tests/RunCMake/install/CMP0087-NEW-check.cmake new file mode 100644 index 0000000000..422c53202c --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-NEW-check.cmake @@ -0,0 +1,7 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -P ${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake + OUTPUT_VARIABLE out ERROR_VARIABLE err) +if(NOT out MATCHES "-- Install configuration: .*-- codegenexlib") + string(REGEX REPLACE "\n" "\n " out " ${out}") + string(APPEND RunCMake_TEST_FAILED + "\"-- codegenexlib\" was not found:\n${out}") +endif() diff --git a/Tests/RunCMake/install/CMP0087-NEW.cmake b/Tests/RunCMake/install/CMP0087-NEW.cmake new file mode 100644 index 0000000000..01779609cd --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-NEW.cmake @@ -0,0 +1,3 @@ +# Need a new directory scope, not just a new policy scope +# to test this correctly +add_subdirectory(CMP0087-NEW) diff --git a/Tests/RunCMake/install/CMP0087-NEW/CMakeLists.txt b/Tests/RunCMake/install/CMP0087-NEW/CMakeLists.txt new file mode 100644 index 0000000000..07b4589cf1 --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-NEW/CMakeLists.txt @@ -0,0 +1,7 @@ +# Note that it is the policy settings at the end of the directory +# scope that will be used when deciding whether or not generator +# expressions should be evaluated in the installed code. +cmake_policy(VERSION 3.13) +cmake_policy(SET CMP0087 NEW) +add_library( codegenexlib INTERFACE ) +install(CODE "message( STATUS \"$<TARGET_PROPERTY:codegenexlib,NAME>\")") diff --git a/Tests/RunCMake/install/CMP0087-OLD-check.cmake b/Tests/RunCMake/install/CMP0087-OLD-check.cmake new file mode 100644 index 0000000000..c5984bca78 --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-OLD-check.cmake @@ -0,0 +1,8 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -P ${RunCMake_TEST_BINARY_DIR}/cmake_install.cmake + OUTPUT_VARIABLE out ERROR_VARIABLE err) + +if(NOT out MATCHES "-- Install configuration: .*-- \\$<TARGET_PROPERTY:codegenexlib,NAME>") + string(REGEX REPLACE "\n" "\n " out " ${out}") + string(APPEND RunCMake_TEST_FAILED + "\"-- $<TARGET_PROPERTY:codegenexlib,NAME>\" was not found:\n${out}") +endif() diff --git a/Tests/RunCMake/install/CMP0087-OLD.cmake b/Tests/RunCMake/install/CMP0087-OLD.cmake new file mode 100644 index 0000000000..e7ed4ee98a --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-OLD.cmake @@ -0,0 +1,3 @@ +# Need a new directory scope, not just a new policy scope +# to test this correctly +add_subdirectory(CMP0087-OLD) diff --git a/Tests/RunCMake/install/CMP0087-OLD/CMakeLists.txt b/Tests/RunCMake/install/CMP0087-OLD/CMakeLists.txt new file mode 100644 index 0000000000..b1d4e2e7d7 --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-OLD/CMakeLists.txt @@ -0,0 +1,6 @@ +# Note that it is the policy settings at the end of the directory +# scope that will be used when deciding whether or not generator +# expressions should be evaluated in the installed code. +cmake_policy(VERSION 3.13) +cmake_policy(SET CMP0087 OLD) +install(CODE "message( STATUS \"$<TARGET_PROPERTY:codegenexlib,NAME>\")") diff --git a/Tests/RunCMake/install/CMP0087-WARN-stderr.txt b/Tests/RunCMake/install/CMP0087-WARN-stderr.txt new file mode 100644 index 0000000000..75fbf2c0c5 --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-WARN-stderr.txt @@ -0,0 +1,5 @@ +CMake Warning (dev) in CMakeLists.txt: + Policy CMP0087 is not set: Install CODE|SCRIPT allow the use of generator + expressions. Run "cmake --help-policy CMP0087" for policy details. Use + the cmake_policy command to set the policy and suppress this warning. +This warning is for project developers. Use -Wno-dev to suppress it. diff --git a/Tests/RunCMake/install/CMP0087-WARN.cmake b/Tests/RunCMake/install/CMP0087-WARN.cmake new file mode 100644 index 0000000000..3b8513d640 --- /dev/null +++ b/Tests/RunCMake/install/CMP0087-WARN.cmake @@ -0,0 +1,2 @@ +add_library( codegenexlib INTERFACE ) +install(CODE "message( STATUS \"$<TARGET_PROPERTY:codegenexlib,NAME>\")") diff --git a/Tests/RunCMake/install/RunCMakeTest.cmake b/Tests/RunCMake/install/RunCMakeTest.cmake index f7e1dee214..28e8ec4d7d 100644 --- a/Tests/RunCMake/install/RunCMakeTest.cmake +++ b/Tests/RunCMake/install/RunCMakeTest.cmake @@ -63,6 +63,9 @@ run_cmake(EXPORT-OldIFace) run_cmake(CMP0062-OLD) run_cmake(CMP0062-NEW) run_cmake(CMP0062-WARN) +run_cmake(CMP0087-OLD) +run_cmake(CMP0087-NEW) +run_cmake(CMP0087-WARN) run_cmake(TARGETS-NAMELINK_COMPONENT-bad-all) run_cmake(TARGETS-NAMELINK_COMPONENT-bad-exc) run_cmake(FILES-DESTINATION-TYPE) |