summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Chronopoulos <patches@crondog.com>2018-11-29 21:11:07 +1100
committerCraig Scott <craig.scott@crascit.com>2018-12-23 09:03:38 +1100
commit25cae1e85d501c463141388e4eb580bdfae6ed2f (patch)
tree5028fc6c22c526e2b67a4539b6d0a7b69747b17a
parentcb995ddea2d633310b270e99d020fe490fff5ec7 (diff)
downloadcmake-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.rst5
-rw-r--r--Help/manual/cmake-policies.7.rst1
-rw-r--r--Help/policy/CMP0087.rst29
-rw-r--r--Help/release/dev/install-code-script-genex.rst5
-rw-r--r--Source/cmInstallScriptGenerator.cxx70
-rw-r--r--Source/cmInstallScriptGenerator.h14
-rw-r--r--Source/cmPolicies.h6
-rw-r--r--Tests/RunCMake/install/CMP0087-NEW-check.cmake7
-rw-r--r--Tests/RunCMake/install/CMP0087-NEW.cmake3
-rw-r--r--Tests/RunCMake/install/CMP0087-NEW/CMakeLists.txt7
-rw-r--r--Tests/RunCMake/install/CMP0087-OLD-check.cmake8
-rw-r--r--Tests/RunCMake/install/CMP0087-OLD.cmake3
-rw-r--r--Tests/RunCMake/install/CMP0087-OLD/CMakeLists.txt6
-rw-r--r--Tests/RunCMake/install/CMP0087-WARN-stderr.txt5
-rw-r--r--Tests/RunCMake/install/CMP0087-WARN.cmake2
-rw-r--r--Tests/RunCMake/install/RunCMakeTest.cmake3
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)