summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Help/command/define_property.rst8
-rw-r--r--Help/release/dev/target-properties-from-variables.rst5
-rw-r--r--Source/cmDefinePropertyCommand.cxx44
-rw-r--r--Source/cmPropertyDefinition.cxx17
-rw-r--r--Source/cmPropertyDefinition.h22
-rw-r--r--Source/cmState.cxx6
-rw-r--r--Source/cmState.h8
-rw-r--r--Source/cmTarget.cxx11
-rw-r--r--Tests/RunCMake/define_property/RunCMakeTest.cmake6
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1-result.txt1
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1-stderr.txt4
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1.cmake3
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2-result.txt1
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2-stderr.txt4
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2.cmake3
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix-result.txt1
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix-stderr.txt5
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix.cmake3
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target-result.txt1
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target-stderr.txt5
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target.cmake3
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-subdirectory/CMakeLists.txt11
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix-result.txt1
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix-stderr.txt5
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix.cmake3
-rw-r--r--Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE.cmake29
-rw-r--r--Tests/RunCMake/define_property/main.c4
27 files changed, 198 insertions, 16 deletions
diff --git a/Help/command/define_property.rst b/Help/command/define_property.rst
index 9474513696..3bd958e39c 100644
--- a/Help/command/define_property.rst
+++ b/Help/command/define_property.rst
@@ -9,7 +9,8 @@ Define and document custom properties.
TEST | VARIABLE | CACHED_VARIABLE>
PROPERTY <name> [INHERITED]
[BRIEF_DOCS <brief-doc> [docs...]]
- [FULL_DOCS <full-doc> [docs...]])
+ [FULL_DOCS <full-doc> [docs...]]
+ [INITIALIZE_FROM_VARIABLE <variable>])
Defines one property in a scope for use with the :command:`set_property` and
:command:`get_property` commands. This is primarily useful to associate
@@ -57,3 +58,8 @@ The ``BRIEF_DOCS`` and ``FULL_DOCS`` options are followed by strings to be
associated with the property as its brief and full documentation.
Corresponding options to the :command:`get_property` command will retrieve
the documentation.
+
+The ``INITIALIZE_FROM_VARIABLE`` option is followed by the name of a variable
+from which to initialize the property. The variable name must end with the
+property name, must have a prefix before the property name, and must not begin
+with ``CMAKE_`` or ``_CMAKE_``.
diff --git a/Help/release/dev/target-properties-from-variables.rst b/Help/release/dev/target-properties-from-variables.rst
new file mode 100644
index 0000000000..99857c48b6
--- /dev/null
+++ b/Help/release/dev/target-properties-from-variables.rst
@@ -0,0 +1,5 @@
+target-properties-from-variables
+--------------------------------
+
+* The :command:`define_property` command gained a new
+ ``INITIALIZE_FROM_VARIABLE`` argument.
diff --git a/Source/cmDefinePropertyCommand.cxx b/Source/cmDefinePropertyCommand.cxx
index 10c36cd3ea..7a2f34fd56 100644
--- a/Source/cmDefinePropertyCommand.cxx
+++ b/Source/cmDefinePropertyCommand.cxx
@@ -2,6 +2,9 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmDefinePropertyCommand.h"
+#include <algorithm>
+#include <iterator>
+
#include <cmext/string_view>
#include "cmArgumentParser.h"
@@ -50,12 +53,14 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args,
std::string PropertyName;
std::vector<std::string> BriefDocs;
std::vector<std::string> FullDocs;
+ std::string initializeFromVariable;
cmArgumentParser<void> parser;
parser.Bind("PROPERTY"_s, PropertyName);
parser.Bind("BRIEF_DOCS"_s, BriefDocs);
parser.Bind("FULL_DOCS"_s, FullDocs);
parser.Bind("INHERITED"_s, inherited);
+ parser.Bind("INITIALIZE_FROM_VARIABLE"_s, initializeFromVariable);
std::vector<std::string> invalidArgs;
parser.Parse(cmMakeRange(args).advance(1), &invalidArgs);
@@ -71,10 +76,47 @@ bool cmDefinePropertyCommand(std::vector<std::string> const& args,
return false;
}
+ if (!initializeFromVariable.empty()) {
+ // Make sure property scope is TARGET.
+ if (scope != cmProperty::TARGET) {
+ status.SetError(
+ "Scope must be TARGET if INITIALIZE_FROM_VARIABLE is specified");
+ return false;
+ }
+
+ // Make sure the variable has the property name as a suffix.
+ if (!cmHasSuffix(initializeFromVariable, PropertyName)) {
+ status.SetError(cmStrCat("Variable name \"", initializeFromVariable,
+ "\" does not end with property name \"",
+ PropertyName, "\""));
+ return false;
+ }
+ if (initializeFromVariable == PropertyName) {
+ status.SetError(cmStrCat(
+ "Variable name must have a non-empty prefix before property name \"",
+ PropertyName, "\""));
+ return false;
+ }
+ }
+
+ // Make sure the variable is not reserved.
+ static constexpr const char* reservedPrefixes[] = {
+ "CMAKE_",
+ "_CMAKE_",
+ };
+ if (std::any_of(std::begin(reservedPrefixes), std::end(reservedPrefixes),
+ [&initializeFromVariable](const char* prefix) {
+ return cmHasPrefix(initializeFromVariable, prefix);
+ })) {
+ status.SetError(
+ cmStrCat("variable name \"", initializeFromVariable, "\" is reserved"));
+ return false;
+ }
+
// Actually define the property.
status.GetMakefile().GetState()->DefineProperty(
PropertyName, scope, cmJoin(BriefDocs, ""), cmJoin(FullDocs, ""),
- inherited);
+ inherited, initializeFromVariable);
return true;
}
diff --git a/Source/cmPropertyDefinition.cxx b/Source/cmPropertyDefinition.cxx
index 1796bb8d0e..22723b9fd1 100644
--- a/Source/cmPropertyDefinition.cxx
+++ b/Source/cmPropertyDefinition.cxx
@@ -6,31 +6,34 @@
cmPropertyDefinition::cmPropertyDefinition(std::string shortDescription,
std::string fullDescription,
- bool chained)
+ bool chained,
+ std::string initializeFromVariable)
: ShortDescription(std::move(shortDescription))
, FullDescription(std::move(fullDescription))
, Chained(chained)
+ , InitializeFromVariable(std::move(initializeFromVariable))
{
}
void cmPropertyDefinitionMap::DefineProperty(
const std::string& name, cmProperty::ScopeType scope,
const std::string& ShortDescription, const std::string& FullDescription,
- bool chain)
+ bool chain, const std::string& initializeFromVariable)
{
- auto it = this->Map_.find(key_type(name, scope));
+ auto it = this->Map_.find(KeyType(name, scope));
if (it == this->Map_.end()) {
// try_emplace() since C++17
- this->Map_.emplace(
- std::piecewise_construct, std::forward_as_tuple(name, scope),
- std::forward_as_tuple(ShortDescription, FullDescription, chain));
+ this->Map_.emplace(std::piecewise_construct,
+ std::forward_as_tuple(name, scope),
+ std::forward_as_tuple(ShortDescription, FullDescription,
+ chain, initializeFromVariable));
}
}
cmPropertyDefinition const* cmPropertyDefinitionMap::GetPropertyDefinition(
const std::string& name, cmProperty::ScopeType scope) const
{
- auto it = this->Map_.find(key_type(name, scope));
+ auto it = this->Map_.find(KeyType(name, scope));
if (it != this->Map_.end()) {
return &it->second;
}
diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h
index fca936e29a..9dd2cfe26d 100644
--- a/Source/cmPropertyDefinition.h
+++ b/Source/cmPropertyDefinition.h
@@ -22,7 +22,8 @@ class cmPropertyDefinition
public:
/// Constructor
cmPropertyDefinition(std::string shortDescription,
- std::string fullDescription, bool chained);
+ std::string fullDescription, bool chained,
+ std::string initializeFromVariable);
/// Is the property chained?
bool IsChained() const { return this->Chained; }
@@ -39,10 +40,17 @@ public:
return this->FullDescription;
}
+ /// Get the variable the property is initialized from
+ const std::string& GetInitializeFromVariable() const
+ {
+ return this->InitializeFromVariable;
+ }
+
private:
std::string ShortDescription;
std::string FullDescription;
bool Chained;
+ std::string InitializeFromVariable;
};
/** \class cmPropertyDefinitionMap
@@ -54,13 +62,19 @@ public:
// define the property
void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
const std::string& ShortDescription,
- const std::string& FullDescription, bool chain);
+ const std::string& FullDescription, bool chain,
+ const std::string& initializeFromVariable);
// get the property definition if present, otherwise nullptr
cmPropertyDefinition const* GetPropertyDefinition(
const std::string& name, cmProperty::ScopeType scope) const;
+ using KeyType = std::pair<std::string, cmProperty::ScopeType>;
+ const std::map<KeyType, cmPropertyDefinition>& GetMap() const
+ {
+ return this->Map_;
+ }
+
private:
- using key_type = std::pair<std::string, cmProperty::ScopeType>;
- std::map<key_type, cmPropertyDefinition> Map_;
+ std::map<KeyType, cmPropertyDefinition> Map_;
};
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 07b4759d1e..f1144e15ae 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -327,10 +327,12 @@ cmStateSnapshot cmState::Reset()
void cmState::DefineProperty(const std::string& name,
cmProperty::ScopeType scope,
const std::string& ShortDescription,
- const std::string& FullDescription, bool chained)
+ const std::string& FullDescription, bool chained,
+ const std::string& initializeFromVariable)
{
this->PropertyDefinitions.DefineProperty(name, scope, ShortDescription,
- FullDescription, chained);
+ FullDescription, chained,
+ initializeFromVariable);
}
cmPropertyDefinition const* cmState::GetPropertyDefinition(
diff --git a/Source/cmState.h b/Source/cmState.h
index b834bbaf9e..4f2b7df9e0 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -133,12 +133,18 @@ public:
// Define a property
void DefineProperty(const std::string& name, cmProperty::ScopeType scope,
const std::string& ShortDescription,
- const std::string& FullDescription, bool chain = false);
+ const std::string& FullDescription, bool chain = false,
+ const std::string& initializeFromVariable = "");
// get property definition
cmPropertyDefinition const* GetPropertyDefinition(
const std::string& name, cmProperty::ScopeType scope) const;
+ const cmPropertyDefinitionMap& GetPropertyDefinitions() const
+ {
+ return this->PropertyDefinitions;
+ }
+
bool IsPropertyChained(const std::string& name,
cmProperty::ScopeType scope) const;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index c5703a1ae3..ad19e03adb 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -28,6 +28,7 @@
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmProperty.h"
+#include "cmPropertyDefinition.h"
#include "cmPropertyMap.h"
#include "cmRange.h"
#include "cmSourceFile.h"
@@ -557,6 +558,16 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
}
}
}
+
+ for (auto const& prop : mf->GetState()->GetPropertyDefinitions().GetMap()) {
+ if (prop.first.second == cmProperty::TARGET &&
+ !prop.second.GetInitializeFromVariable().empty()) {
+ if (auto value =
+ mf->GetDefinition(prop.second.GetInitializeFromVariable())) {
+ this->SetProperty(prop.first.first, value);
+ }
+ }
+ }
}
cmTarget::cmTarget(cmTarget&&) noexcept = default;
diff --git a/Tests/RunCMake/define_property/RunCMakeTest.cmake b/Tests/RunCMake/define_property/RunCMakeTest.cmake
index 5cb581b307..7d7c75b18f 100644
--- a/Tests/RunCMake/define_property/RunCMakeTest.cmake
+++ b/Tests/RunCMake/define_property/RunCMakeTest.cmake
@@ -1,3 +1,9 @@
include(RunCMake)
run_cmake(define_property)
+run_cmake(define_property-INITIALIZE_FROM_VARIABLE)
+run_cmake(define_property-INITIALIZE_FROM_VARIABLE-invalid_1)
+run_cmake(define_property-INITIALIZE_FROM_VARIABLE-invalid_2)
+run_cmake(define_property-INITIALIZE_FROM_VARIABLE-non_target)
+run_cmake(define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix)
+run_cmake(define_property-INITIALIZE_FROM_VARIABLE-no_prefix)
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1-result.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1-result.txt
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1-result.txt
@@ -0,0 +1 @@
+
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1-stderr.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1-stderr.txt
new file mode 100644
index 0000000000..a7903c9d3e
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at define_property-INITIALIZE_FROM_VARIABLE-invalid_1\.cmake:[0-9]+ \(define_property\):
+ define_property variable name "CMAKE_PROP1" is reserved
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1.cmake b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1.cmake
new file mode 100644
index 0000000000..873263af89
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_1.cmake
@@ -0,0 +1,3 @@
+define_property(TARGET PROPERTY PROP1
+ INITIALIZE_FROM_VARIABLE CMAKE_PROP1
+ )
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2-result.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2-result.txt
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2-result.txt
@@ -0,0 +1 @@
+
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2-stderr.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2-stderr.txt
new file mode 100644
index 0000000000..ea6bc8620d
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at define_property-INITIALIZE_FROM_VARIABLE-invalid_2\.cmake:[0-9]+ \(define_property\):
+ define_property variable name "_CMAKE_PROP1" is reserved
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2.cmake b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2.cmake
new file mode 100644
index 0000000000..95945a3453
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-invalid_2.cmake
@@ -0,0 +1,3 @@
+define_property(TARGET PROPERTY PROP1
+ INITIALIZE_FROM_VARIABLE _CMAKE_PROP1
+ )
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix-result.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix-stderr.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix-stderr.txt
new file mode 100644
index 0000000000..fc9099cf18
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at define_property-INITIALIZE_FROM_VARIABLE-no_prefix\.cmake:[0-9]+ \(define_property\):
+ define_property Variable name must have a non-empty prefix before property
+ name "PROP1"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix.cmake b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix.cmake
new file mode 100644
index 0000000000..cc39b57c03
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-no_prefix.cmake
@@ -0,0 +1,3 @@
+define_property(TARGET PROPERTY PROP1
+ INITIALIZE_FROM_VARIABLE PROP1
+ )
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target-result.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target-stderr.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target-stderr.txt
new file mode 100644
index 0000000000..81596965a5
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at define_property-INITIALIZE_FROM_VARIABLE-non_target\.cmake:[0-9]+ \(define_property\):
+ define_property Scope must be TARGET if INITIALIZE_FROM_VARIABLE is
+ specified
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target.cmake b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target.cmake
new file mode 100644
index 0000000000..270e3b8d9d
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-non_target.cmake
@@ -0,0 +1,3 @@
+define_property(GLOBAL PROPERTY PROP1
+ INITIALIZE_FROM_VARIABLE Test_PROP1
+ )
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-subdirectory/CMakeLists.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-subdirectory/CMakeLists.txt
new file mode 100644
index 0000000000..67c186dd6c
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-subdirectory/CMakeLists.txt
@@ -0,0 +1,11 @@
+define_property(TARGET PROPERTY PROP2
+ INITIALIZE_FROM_VARIABLE Test_PROP2
+ )
+define_property(TARGET PROPERTY PROP3
+ INITIALIZE_FROM_VARIABLE Test_PROP3
+ )
+
+add_executable(sub_exe ../main.c)
+assert_prop_eq(sub_exe PROP1 "Hello")
+assert_prop_eq(sub_exe PROP2 "world")
+assert_prop_eq(sub_exe PROP3 "!")
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix-result.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix-result.txt
new file mode 100644
index 0000000000..d00491fd7e
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix-stderr.txt b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix-stderr.txt
new file mode 100644
index 0000000000..48c7e9084c
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix\.cmake:[0-9]+ \(define_property\):
+ define_property Variable name "Test_PROP2" does not end with property name
+ "PROP1"
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix.cmake b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix.cmake
new file mode 100644
index 0000000000..7566861c9e
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE-wrong_suffix.cmake
@@ -0,0 +1,3 @@
+define_property(TARGET PROPERTY PROP1
+ INITIALIZE_FROM_VARIABLE Test_PROP2
+ )
diff --git a/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE.cmake b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE.cmake
new file mode 100644
index 0000000000..d866fc983e
--- /dev/null
+++ b/Tests/RunCMake/define_property/define_property-INITIALIZE_FROM_VARIABLE.cmake
@@ -0,0 +1,29 @@
+enable_language(C)
+
+function(assert_prop_eq tgt name value)
+ get_property(actual_value TARGET ${tgt} PROPERTY ${name})
+ if(NOT actual_value STREQUAL value)
+ message(SEND_ERROR "Expected value of ${name}:\n ${value}\nActual value:\n ${actual_value}")
+ endif()
+endfunction()
+
+function(assert_prop_undef tgt name)
+ get_property(actual_value TARGET ${tgt} PROPERTY ${name})
+ if(DEFINED actual_value)
+ message(SEND_ERROR "Expected ${name} to be undefined, actual value:\n ${actual_value}")
+ endif()
+endfunction()
+
+set(Test_PROP1 "Hello")
+set(Test_PROP2 "world")
+set(Test_PROP3 "!")
+define_property(TARGET PROPERTY PROP1
+ INITIALIZE_FROM_VARIABLE Test_PROP1
+ )
+
+add_subdirectory(define_property-INITIALIZE_FROM_VARIABLE-subdirectory)
+
+add_executable(top_exe main.c)
+assert_prop_eq(top_exe PROP1 "Hello")
+assert_prop_eq(top_exe PROP2 "world")
+assert_prop_eq(top_exe PROP3 "!")
diff --git a/Tests/RunCMake/define_property/main.c b/Tests/RunCMake/define_property/main.c
new file mode 100644
index 0000000000..8488f4e58f
--- /dev/null
+++ b/Tests/RunCMake/define_property/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}