summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/CMakeLists.txt2
-rw-r--r--Source/cmGeneratorTarget.cxx57
-rw-r--r--Source/cmGeneratorTarget.h4
-rw-r--r--Source/cmGetPropertyCommand.cxx15
-rw-r--r--Source/cmGetTargetPropertyCommand.cxx13
-rw-r--r--Source/cmListFileCache.h2
-rw-r--r--Source/cmTarget.cxx458
-rw-r--r--Source/cmTarget.h19
-rw-r--r--Source/cmTargetPropertyComputer.cxx99
-rw-r--r--Source/cmTargetPropertyComputer.h110
-rw-r--r--Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-LOCATION-stderr.txt4
-rwxr-xr-xbootstrap1
12 files changed, 493 insertions, 291 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 7d82a51..71892ba 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -364,6 +364,8 @@ set(SRCS
cmSystemTools.h
cmTarget.cxx
cmTarget.h
+ cmTargetPropertyComputer.cxx
+ cmTargetPropertyComputer.h
cmTargetExport.h
cmTest.cxx
cmTest.h
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index f11149a..b16cfc6 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -18,6 +18,7 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
+#include "cmTargetPropertyComputer.h"
#include "cm_auto_ptr.hxx"
#include "cmake.h"
@@ -42,6 +43,28 @@
#define UNORDERED_SET std::set
#endif
+template <>
+const char* cmTargetPropertyComputer::GetSources<cmGeneratorTarget>(
+ cmGeneratorTarget const* tgt, cmMessenger* /* messenger */,
+ cmListFileBacktrace const& /* context */)
+{
+ return tgt->GetSourcesProperty();
+}
+
+template <>
+const char* cmTargetPropertyComputer::ComputeLocationForBuild<
+ cmGeneratorTarget>(cmGeneratorTarget const* tgt)
+{
+ return tgt->GetLocation("");
+}
+
+template <>
+const char* cmTargetPropertyComputer::ComputeLocation<cmGeneratorTarget>(
+ cmGeneratorTarget const* tgt, const std::string& config)
+{
+ return tgt->GetLocation(config);
+}
+
class cmGeneratorTarget::TargetPropertyEntry
{
static cmLinkImplItem NoLinkImplItem;
@@ -320,6 +343,26 @@ cmGeneratorTarget::~cmGeneratorTarget()
cmDeleteAll(this->LinkInformation);
}
+const char* cmGeneratorTarget::GetSourcesProperty() const
+{
+ std::vector<std::string> values;
+ for (std::vector<cmGeneratorTarget::TargetPropertyEntry *>::const_iterator
+ it = this->SourceEntries.begin(),
+ end = this->SourceEntries.end();
+ it != end; ++it) {
+ values.push_back((*it)->ge->GetInput());
+ }
+ static std::string value;
+ value.clear();
+ value = cmJoin(values, "");
+ return value.c_str();
+}
+
+cmGlobalGenerator* cmGeneratorTarget::GetGlobalGenerator() const
+{
+ return this->GetLocalGenerator()->GetGlobalGenerator();
+}
+
cmLocalGenerator* cmGeneratorTarget::GetLocalGenerator() const
{
return this->LocalGenerator;
@@ -354,6 +397,18 @@ std::string cmGeneratorTarget::GetExportName() const
const char* cmGeneratorTarget::GetProperty(const std::string& prop) const
{
+ if (!cmTargetPropertyComputer::PassesWhitelist(
+ this->GetType(), prop, this->Makefile->GetMessenger(),
+ this->GetBacktrace())) {
+ return 0;
+ }
+ if (const char* result = cmTargetPropertyComputer::GetProperty(
+ this, prop, this->Makefile->GetMessenger(), this->GetBacktrace())) {
+ return result;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return CM_NULLPTR;
+ }
return this->Target->GetProperty(prop);
}
@@ -3966,7 +4021,7 @@ void cmGeneratorTarget::ComputeVersionedName(std::string& vName,
std::vector<std::string> cmGeneratorTarget::GetPropertyKeys() const
{
- cmPropertyMap propsObject = this->Target->GetProperties();
+ cmPropertyMap const& propsObject = this->Target->GetProperties();
std::vector<std::string> props;
props.reserve(propsObject.size());
for (cmPropertyMap::const_iterator it = propsObject.begin();
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 9382726..8e5a02d 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -32,6 +32,8 @@ public:
cmLocalGenerator* GetLocalGenerator() const;
+ cmGlobalGenerator* GetGlobalGenerator() const;
+
bool IsImported() const;
bool IsImportedGloballyVisible() const;
const char* GetLocation(const std::string& config) const;
@@ -533,6 +535,8 @@ public:
std::string GetFortranModuleDirectory(std::string const& working_dir) const;
+ const char* GetSourcesProperty() const;
+
private:
void AddSourceCommon(const std::string& src);
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index ba03568..39445dd 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -6,6 +6,7 @@
#include "cmPropertyDefinition.h"
#include "cmSourceFile.h"
#include "cmState.h"
+#include "cmTargetPropertyComputer.h"
#include "cmTest.h"
#include "cmake.h"
@@ -246,8 +247,18 @@ bool cmGetPropertyCommand::HandleTargetMode()
}
return this->StoreResult(CM_NULLPTR);
}
- return this->StoreResult(
- target->GetProperty(this->PropertyName, this->Makefile));
+ const char* prop_cstr = 0;
+ cmListFileBacktrace bt = this->Makefile->GetBacktrace();
+ cmMessenger* messenger = this->Makefile->GetMessenger();
+ if (cmTargetPropertyComputer::PassesWhitelist(
+ target->GetType(), this->PropertyName, messenger, bt)) {
+ prop_cstr =
+ target->GetComputedProperty(this->PropertyName, messenger, bt);
+ if (!prop_cstr) {
+ prop_cstr = target->GetProperty(this->PropertyName);
+ }
+ }
+ return this->StoreResult(prop_cstr);
}
std::ostringstream e;
e << "could not find TARGET " << this->Name
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index fe09442..6a816d8 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGetTargetPropertyCommand.h"
+#include "cmTargetPropertyComputer.h"
+
// cmSetTargetPropertyCommand
bool cmGetTargetPropertyCommand::InitialPass(
std::vector<std::string> const& args, cmExecutionStatus&)
@@ -22,7 +24,16 @@ bool cmGetTargetPropertyCommand::InitialPass(
prop_exists = true;
}
} else if (!args[2].empty()) {
- const char* prop_cstr = tgt->GetProperty(args[2], this->Makefile);
+ const char* prop_cstr = 0;
+ cmListFileBacktrace bt = this->Makefile->GetBacktrace();
+ cmMessenger* messenger = this->Makefile->GetMessenger();
+ if (cmTargetPropertyComputer::PassesWhitelist(tgt->GetType(), args[2],
+ messenger, bt)) {
+ prop_cstr = tgt->GetComputedProperty(args[2], messenger, bt);
+ if (!prop_cstr) {
+ prop_cstr = tgt->GetProperty(args[2]);
+ }
+ }
if (prop_cstr) {
prop = prop_cstr;
prop_exists = true;
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 4dacee0..fd779c7 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -120,6 +120,8 @@ public:
cmListFileBacktrace& operator=(cmListFileBacktrace const& r);
~cmListFileBacktrace();
+ cmState::Snapshot GetBottom() const { return this->Bottom; }
+
// Get a backtrace with the given file scope added to the top.
// May not be called until after construction with a valid snapshot.
cmListFileBacktrace Push(std::string const& file) const;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 651bcc8..3a22309 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -8,11 +8,13 @@
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
+#include "cmMessenger.h"
#include "cmOutputConverter.h"
#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSystemTools.h"
+#include "cmTargetPropertyComputer.h"
#include "cmake.h"
#include <algorithm>
@@ -33,6 +35,134 @@
#define UNORDERED_SET std::set
#endif
+template <>
+const char* cmTargetPropertyComputer::ComputeLocationForBuild<cmTarget>(
+ cmTarget const* tgt)
+{
+ static std::string loc;
+ if (tgt->IsImported()) {
+ loc = tgt->ImportedGetFullPath("", false);
+ return loc.c_str();
+ }
+
+ cmGlobalGenerator* gg = tgt->GetGlobalGenerator();
+ if (!gg->GetConfigureDoneCMP0026()) {
+ gg->CreateGenerationObjects();
+ }
+ cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
+ loc = gt->GetLocationForBuild();
+ return loc.c_str();
+}
+
+template <>
+const char* cmTargetPropertyComputer::ComputeLocation<cmTarget>(
+ cmTarget const* tgt, const std::string& config)
+{
+ static std::string loc;
+ if (tgt->IsImported()) {
+ loc = tgt->ImportedGetFullPath(config, false);
+ return loc.c_str();
+ }
+
+ cmGlobalGenerator* gg = tgt->GetGlobalGenerator();
+ if (!gg->GetConfigureDoneCMP0026()) {
+ gg->CreateGenerationObjects();
+ }
+ cmGeneratorTarget* gt = gg->FindGeneratorTarget(tgt->GetName());
+ loc = gt->GetFullPath(config, false);
+ return loc.c_str();
+}
+
+template <>
+const char* cmTargetPropertyComputer::GetSources<cmTarget>(
+ cmTarget const* tgt, cmMessenger* messenger,
+ cmListFileBacktrace const& context)
+{
+ cmStringRange entries = tgt->GetSourceEntries();
+ if (entries.empty()) {
+ return CM_NULLPTR;
+ }
+
+ std::ostringstream ss;
+ const char* sep = "";
+ for (std::vector<std::string>::const_iterator i = entries.begin();
+ i != entries.end(); ++i) {
+ std::string const& entry = *i;
+
+ std::vector<std::string> files;
+ cmSystemTools::ExpandListArgument(entry, files);
+ for (std::vector<std::string>::const_iterator li = files.begin();
+ li != files.end(); ++li) {
+ if (cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
+ (*li)[li->size() - 1] == '>') {
+ std::string objLibName = li->substr(17, li->size() - 18);
+
+ if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ continue;
+ }
+
+ bool addContent = false;
+ bool noMessage = true;
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch (context.GetBottom().GetPolicy(cmPolicies::CMP0051)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n";
+ noMessage = false;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ addContent = true;
+ }
+ if (!noMessage) {
+ e << "Target \"" << tgt->GetName()
+ << "\" contains "
+ "$<TARGET_OBJECTS> generator expression in its sources "
+ "list. "
+ "This content was not previously part of the SOURCES "
+ "property "
+ "when that property was read at configure time. Code "
+ "reading "
+ "that property needs to be adapted to ignore the generator "
+ "expression using the string(GENEX_STRIP) command.";
+ messenger->IssueMessage(messageType, e.str(), context);
+ }
+ if (addContent) {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ }
+ } else if (cmGeneratorExpression::Find(*li) == std::string::npos) {
+ ss << sep;
+ sep = ";";
+ ss << *li;
+ } else {
+ cmSourceFile* sf = tgt->GetMakefile()->GetOrCreateSource(*li);
+ // Construct what is known about this source file location.
+ cmSourceFileLocation const& location = sf->GetLocation();
+ std::string sname = location.GetDirectory();
+ if (!sname.empty()) {
+ sname += "/";
+ }
+ sname += location.GetName();
+
+ ss << sep;
+ sep = ";";
+ // Append this list entry.
+ ss << sname;
+ }
+ }
+ }
+ static std::string srcs;
+ srcs = ss.str();
+ return srcs.c_str();
+}
+
class cmTargetInternals
{
public:
@@ -270,6 +400,11 @@ cmTarget::cmTarget(std::string const& name, cmState::TargetType type,
}
}
+cmGlobalGenerator* cmTarget::GetGlobalGenerator() const
+{
+ return this->GetMakefile()->GetGlobalGenerator();
+}
+
void cmTarget::AddUtility(const std::string& u, cmMakefile* makefile)
{
if (this->Utilities.insert(u).second && makefile) {
@@ -705,43 +840,11 @@ cmBacktraceRange cmTarget::GetLinkImplementationBacktraces() const
return cmMakeRange(this->Internal->LinkImplementationPropertyBacktraces);
}
-static bool whiteListedInterfaceProperty(const std::string& prop)
-{
- if (cmHasLiteralPrefix(prop, "INTERFACE_")) {
- return true;
- }
- static UNORDERED_SET<std::string> builtIns;
- if (builtIns.empty()) {
- builtIns.insert("COMPATIBLE_INTERFACE_BOOL");
- builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MAX");
- builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MIN");
- builtIns.insert("COMPATIBLE_INTERFACE_STRING");
- builtIns.insert("EXPORT_NAME");
- builtIns.insert("IMPORTED");
- builtIns.insert("NAME");
- builtIns.insert("TYPE");
- }
-
- if (builtIns.count(prop)) {
- return true;
- }
-
- if (cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) {
- return true;
- }
-
- return false;
-}
-
void cmTarget::SetProperty(const std::string& prop, const char* value)
{
- if (this->GetType() == cmState::INTERFACE_LIBRARY &&
- !whiteListedInterfaceProperty(prop)) {
- std::ostringstream e;
- e << "INTERFACE_LIBRARY targets may only have whitelisted properties. "
- "The property \""
- << prop << "\" is not allowed.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ if (!cmTargetPropertyComputer::PassesWhitelist(
+ this->GetType(), prop, this->Makefile->GetMessenger(),
+ this->Makefile->GetBacktrace())) {
return;
}
if (prop == "NAME") {
@@ -749,7 +852,20 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
e << "NAME property is read-only\n";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
+ } else if (prop == "EXPORT_NAME" && this->IsImported()) {
+ std::ostringstream e;
+ e << "EXPORT_NAME property can't be set on imported targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ } else if (prop == "SOURCES" && this->IsImported()) {
+ std::ostringstream e;
+ e << "SOURCES property can't be set on imported targets (\"" << this->Name
+ << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
}
+
if (prop == "INCLUDE_DIRECTORIES") {
this->Internal->IncludeDirectoriesEntries.clear();
this->Internal->IncludeDirectoriesBacktraces.clear();
@@ -782,11 +898,6 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
}
- } else if (prop == "EXPORT_NAME" && this->IsImported()) {
- std::ostringstream e;
- e << "EXPORT_NAME property can't be set on imported targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
} else if (prop == "LINK_LIBRARIES") {
this->Internal->LinkImplementationPropertyEntries.clear();
this->Internal->LinkImplementationPropertyBacktraces.clear();
@@ -796,14 +907,6 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt);
}
} else if (prop == "SOURCES") {
- if (this->IsImported()) {
- std::ostringstream e;
- e << "SOURCES property can't be set on imported targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- return;
- }
-
this->Internal->SourceEntries.clear();
this->Internal->SourceBacktraces.clear();
if (value) {
@@ -819,13 +922,9 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
void cmTarget::AppendProperty(const std::string& prop, const char* value,
bool asString)
{
- if (this->GetType() == cmState::INTERFACE_LIBRARY &&
- !whiteListedInterfaceProperty(prop)) {
- std::ostringstream e;
- e << "INTERFACE_LIBRARY targets may only have whitelisted properties. "
- "The property \""
- << prop << "\" is not allowed.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ if (!cmTargetPropertyComputer::PassesWhitelist(
+ this->GetType(), prop, this->Makefile->GetMessenger(),
+ this->Makefile->GetBacktrace())) {
return;
}
if (prop == "NAME") {
@@ -833,6 +932,18 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
e << "NAME property is read-only\n";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
+ } else if (prop == "EXPORT_NAME" && this->IsImported()) {
+ std::ostringstream e;
+ e << "EXPORT_NAME property can't be set on imported targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ } else if (prop == "SOURCES" && this->IsImported()) {
+ std::ostringstream e;
+ e << "SOURCES property can't be set on imported targets (\"" << this->Name
+ << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
}
if (prop == "INCLUDE_DIRECTORIES") {
if (value && *value) {
@@ -858,11 +969,6 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
}
- } else if (prop == "EXPORT_NAME" && this->IsImported()) {
- std::ostringstream e;
- e << "EXPORT_NAME property can't be set on imported targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
} else if (prop == "LINK_LIBRARIES") {
if (value && *value) {
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
@@ -870,13 +976,6 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt);
}
} else if (prop == "SOURCES") {
- if (this->IsImported()) {
- std::ostringstream e;
- e << "SOURCES property can't be set on imported targets (\""
- << this->Name << "\")\n";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- return;
- }
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->SourceEntries.push_back(value);
this->Internal->SourceBacktraces.push_back(lfbt);
@@ -1030,136 +1129,15 @@ void cmTarget::CheckProperty(const std::string& prop,
}
}
-bool cmTarget::HandleLocationPropertyPolicy(cmMakefile* context) const
+const char* cmTarget::GetComputedProperty(
+ const std::string& prop, cmMessenger* messenger,
+ cmListFileBacktrace const& context) const
{
- if (this->IsImported()) {
- return true;
- }
- std::ostringstream e;
- const char* modal = CM_NULLPTR;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch (context->GetPolicyStatus(cmPolicies::CMP0026)) {
- case cmPolicies::WARN:
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n";
- modal = "should";
- case cmPolicies::OLD:
- break;
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::NEW:
- modal = "may";
- messageType = cmake::FATAL_ERROR;
- }
-
- if (modal) {
- e << "The LOCATION property " << modal << " not be read from target \""
- << this->GetName()
- << "\". Use the target name directly with "
- "add_custom_command, or use the generator expression $<TARGET_FILE>, "
- "as appropriate.\n";
- context->IssueMessage(messageType, e.str());
- }
-
- return messageType != cmake::FATAL_ERROR;
+ return cmTargetPropertyComputer::GetProperty(this, prop, messenger, context);
}
const char* cmTarget::GetProperty(const std::string& prop) const
{
- return this->GetProperty(prop, this->Makefile);
-}
-
-const char* cmTarget::GetProperty(const std::string& prop,
- cmMakefile* context) const
-{
- if (this->GetType() == cmState::INTERFACE_LIBRARY &&
- !whiteListedInterfaceProperty(prop)) {
- std::ostringstream e;
- e << "INTERFACE_LIBRARY targets may only have whitelisted properties. "
- "The property \""
- << prop << "\" is not allowed.";
- context->IssueMessage(cmake::FATAL_ERROR, e.str());
- return CM_NULLPTR;
- }
-
- // Watch for special "computed" properties that are dependent on
- // other properties or variables. Always recompute them.
- if (this->GetType() == cmState::EXECUTABLE ||
- this->GetType() == cmState::STATIC_LIBRARY ||
- this->GetType() == cmState::SHARED_LIBRARY ||
- this->GetType() == cmState::MODULE_LIBRARY ||
- this->GetType() == cmState::UNKNOWN_LIBRARY) {
- static const std::string propLOCATION = "LOCATION";
- if (prop == propLOCATION) {
- if (!this->HandleLocationPropertyPolicy(context)) {
- return CM_NULLPTR;
- }
-
- // Set the LOCATION property of the target.
- //
- // For an imported target this is the location of an arbitrary
- // available configuration.
- //
- if (this->IsImported()) {
- this->Properties.SetProperty(
- propLOCATION, this->ImportedGetFullPath("", false).c_str());
- } else {
- // For a non-imported target this is deprecated because it
- // cannot take into account the per-configuration name of the
- // target because the configuration type may not be known at
- // CMake time.
- cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
- if (!gg->GetConfigureDoneCMP0026()) {
- gg->CreateGenerationObjects();
- }
- cmGeneratorTarget* gt = gg->FindGeneratorTarget(this->GetName());
- this->Properties.SetProperty(propLOCATION, gt->GetLocationForBuild());
- }
-
- }
-
- // Support "LOCATION_<CONFIG>".
- else if (cmHasLiteralPrefix(prop, "LOCATION_")) {
- if (!this->HandleLocationPropertyPolicy(context)) {
- return CM_NULLPTR;
- }
- const char* configName = prop.c_str() + 9;
-
- if (this->IsImported()) {
- this->Properties.SetProperty(
- prop, this->ImportedGetFullPath(configName, false).c_str());
- } else {
- cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
- if (!gg->GetConfigureDoneCMP0026()) {
- gg->CreateGenerationObjects();
- }
- cmGeneratorTarget* gt = gg->FindGeneratorTarget(this->GetName());
- this->Properties.SetProperty(
- prop, gt->GetFullPath(configName, false).c_str());
- }
- }
- // Support "<CONFIG>_LOCATION".
- else if (cmHasLiteralSuffix(prop, "_LOCATION") &&
- !cmHasLiteralPrefix(prop, "XCODE_ATTRIBUTE_")) {
- std::string configName(prop.c_str(), prop.size() - 9);
- if (configName != "IMPORTED") {
- if (!this->HandleLocationPropertyPolicy(context)) {
- return CM_NULLPTR;
- }
- if (this->IsImported()) {
- this->Properties.SetProperty(
- prop, this->ImportedGetFullPath(configName, false).c_str());
- } else {
- cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
- if (!gg->GetConfigureDoneCMP0026()) {
- gg->CreateGenerationObjects();
- }
- cmGeneratorTarget* gt = gg->FindGeneratorTarget(this->GetName());
- this->Properties.SetProperty(
- prop, gt->GetFullPath(configName, false).c_str());
- }
- }
- }
- }
static UNORDERED_SET<std::string> specialProps;
#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
MAKE_STATIC_PROP(LINK_LIBRARIES);
@@ -1244,93 +1222,16 @@ const char* cmTarget::GetProperty(const std::string& prop,
return this->GetName().c_str();
}
if (prop == propBINARY_DIR) {
- return this->GetMakefile()->GetCurrentBinaryDirectory();
+ return this->GetMakefile()
+ ->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentBinary();
}
if (prop == propSOURCE_DIR) {
- return this->GetMakefile()->GetCurrentSourceDirectory();
- }
- if (prop == propSOURCES) {
- if (this->Internal->SourceEntries.empty()) {
- return CM_NULLPTR;
- }
-
- std::ostringstream ss;
- const char* sep = "";
- for (std::vector<std::string>::const_iterator i =
- this->Internal->SourceEntries.begin();
- i != this->Internal->SourceEntries.end(); ++i) {
- std::string const& entry = *i;
-
- std::vector<std::string> files;
- cmSystemTools::ExpandListArgument(entry, files);
- for (std::vector<std::string>::const_iterator li = files.begin();
- li != files.end(); ++li) {
- if (cmHasLiteralPrefix(*li, "$<TARGET_OBJECTS:") &&
- (*li)[li->size() - 1] == '>') {
- std::string objLibName = li->substr(17, li->size() - 18);
-
- if (cmGeneratorExpression::Find(objLibName) != std::string::npos) {
- ss << sep;
- sep = ";";
- ss << *li;
- continue;
- }
-
- bool addContent = false;
- bool noMessage = true;
- std::ostringstream e;
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- switch (context->GetPolicyStatus(cmPolicies::CMP0051)) {
- case cmPolicies::WARN:
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n";
- noMessage = false;
- case cmPolicies::OLD:
- break;
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::NEW:
- addContent = true;
- }
- if (!noMessage) {
- e << "Target \"" << this->Name
- << "\" contains "
- "$<TARGET_OBJECTS> generator expression in its sources "
- "list. "
- "This content was not previously part of the SOURCES "
- "property "
- "when that property was read at configure time. Code "
- "reading "
- "that property needs to be adapted to ignore the generator "
- "expression using the string(GENEX_STRIP) command.";
- context->IssueMessage(messageType, e.str());
- }
- if (addContent) {
- ss << sep;
- sep = ";";
- ss << *li;
- }
- } else if (cmGeneratorExpression::Find(*li) == std::string::npos) {
- ss << sep;
- sep = ";";
- ss << *li;
- } else {
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(*li);
- // Construct what is known about this source file location.
- cmSourceFileLocation const& location = sf->GetLocation();
- std::string sname = location.GetDirectory();
- if (!sname.empty()) {
- sname += "/";
- }
- sname += location.GetName();
-
- ss << sep;
- sep = ";";
- // Append this list entry.
- ss << sname;
- }
- }
- }
- this->Properties.SetProperty("SOURCES", ss.str().c_str());
+ return this->GetMakefile()
+ ->GetStateSnapshot()
+ .GetDirectory()
+ .GetCurrentSource();
}
}
@@ -1339,7 +1240,8 @@ const char* cmTarget::GetProperty(const std::string& prop,
const bool chain = this->GetMakefile()->GetState()->IsPropertyChained(
prop, cmProperty::TARGET);
if (chain) {
- return this->Makefile->GetProperty(prop, chain);
+ return this->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
+ prop, chain);
}
}
return retVal;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 3d88688..bd00b3d 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -30,6 +30,7 @@
class cmMakefile;
class cmSourceFile;
+class cmGlobalGenerator;
class cmTargetInternals;
class cmTargetInternalPointer
@@ -76,6 +77,8 @@ public:
*/
cmState::TargetType GetType() const { return this->TargetTypeValue; }
+ cmGlobalGenerator* GetGlobalGenerator() const;
+
///! Set/Get the name of the target
const std::string& GetName() const { return this->Name; }
@@ -197,9 +200,11 @@ public:
void AppendProperty(const std::string& prop, const char* value,
bool asString = false);
const char* GetProperty(const std::string& prop) const;
- const char* GetProperty(const std::string& prop, cmMakefile* context) const;
bool GetPropertyAsBool(const std::string& prop) const;
void CheckProperty(const std::string& prop, cmMakefile* context) const;
+ const char* GetComputedProperty(const std::string& prop,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context) const;
bool IsImported() const { return this->IsImportedTarget; }
bool IsImportedGloballyVisible() const
@@ -208,7 +213,7 @@ public:
}
// Get the properties
- cmPropertyMap& GetProperties() const { return this->Properties; }
+ cmPropertyMap const& GetProperties() const { return this->Properties; }
bool GetMappedConfig(std::string const& desired_config, const char** loc,
const char** imp, std::string& suffix) const;
@@ -267,9 +272,10 @@ public:
bool operator()(cmTarget const* t1, cmTarget const* t2) const;
};
-private:
- bool HandleLocationPropertyPolicy(cmMakefile* context) const;
+ std::string ImportedGetFullPath(const std::string& config,
+ bool implib) const;
+private:
const char* GetSuffixVariableInternal(bool implib) const;
const char* GetPrefixVariableInternal(bool implib) const;
@@ -278,11 +284,8 @@ private:
void SetPropertyDefault(const std::string& property,
const char* default_value);
- std::string ImportedGetFullPath(const std::string& config,
- bool implib) const;
-
private:
- mutable cmPropertyMap Properties;
+ cmPropertyMap Properties;
std::set<std::string> SystemIncludeDirectories;
std::set<std::string> LinkDirectoriesEmmitted;
std::set<std::string> Utilities;
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
new file mode 100644
index 0000000..21408d1
--- /dev/null
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -0,0 +1,99 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#include "cmTargetPropertyComputer.h"
+
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmMessenger.h"
+#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
+#include "cmTarget.h"
+
+#if defined(CMake_HAVE_CXX_UNORDERED_SET)
+#include <unordered_set>
+#define UNORDERED_SET std::unordered_set
+#elif defined(CMAKE_BUILD_WITH_CMAKE)
+#include <cmsys/hash_set.hxx>
+#define UNORDERED_SET cmsys::hash_set
+#else
+#define UNORDERED_SET std::set
+#endif
+
+bool cmTargetPropertyComputer::HandleLocationPropertyPolicy(
+ std::string const& tgtName, cmMessenger* messenger,
+ cmListFileBacktrace const& context)
+{
+ std::ostringstream e;
+ const char* modal = CM_NULLPTR;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ switch (context.GetBottom().GetPolicy(cmPolicies::CMP0026)) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n";
+ modal = "should";
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::NEW:
+ modal = "may";
+ messageType = cmake::FATAL_ERROR;
+ }
+
+ if (modal) {
+ e << "The LOCATION property " << modal << " not be read from target \""
+ << tgtName
+ << "\". Use the target name directly with "
+ "add_custom_command, or use the generator expression $<TARGET_FILE>, "
+ "as appropriate.\n";
+ messenger->IssueMessage(messageType, e.str(), context);
+ }
+
+ return messageType != cmake::FATAL_ERROR;
+}
+
+bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
+ const std::string& prop)
+{
+ if (cmHasLiteralPrefix(prop, "INTERFACE_")) {
+ return true;
+ }
+ static UNORDERED_SET<std::string> builtIns;
+ if (builtIns.empty()) {
+ builtIns.insert("COMPATIBLE_INTERFACE_BOOL");
+ builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MAX");
+ builtIns.insert("COMPATIBLE_INTERFACE_NUMBER_MIN");
+ builtIns.insert("COMPATIBLE_INTERFACE_STRING");
+ builtIns.insert("EXPORT_NAME");
+ builtIns.insert("IMPORTED");
+ builtIns.insert("NAME");
+ builtIns.insert("TYPE");
+ }
+
+ if (builtIns.count(prop)) {
+ return true;
+ }
+
+ if (cmHasLiteralPrefix(prop, "MAP_IMPORTED_CONFIG_")) {
+ return true;
+ }
+
+ return false;
+}
+
+bool cmTargetPropertyComputer::PassesWhitelist(
+ cmState::TargetType tgtType, std::string const& prop, cmMessenger* messenger,
+ cmListFileBacktrace const& context)
+{
+ if (tgtType == cmState::INTERFACE_LIBRARY &&
+ !WhiteListedInterfaceProperty(prop)) {
+ std::ostringstream e;
+ e << "INTERFACE_LIBRARY targets may only have whitelisted properties. "
+ "The property \""
+ << prop << "\" is not allowed.";
+ messenger->IssueMessage(cmake::FATAL_ERROR, e.str(), context);
+ return false;
+ }
+ return true;
+}
diff --git a/Source/cmTargetPropertyComputer.h b/Source/cmTargetPropertyComputer.h
new file mode 100644
index 0000000..ed9a4e2
--- /dev/null
+++ b/Source/cmTargetPropertyComputer.h
@@ -0,0 +1,110 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmTargetPropertyComputer_h
+#define cmTargetPropertyComputer_h
+
+#include <cmConfigure.h> // IWYU pragma: keep
+
+#include "cmListFileCache.h"
+#include "cmSystemTools.h"
+
+#include <map>
+#include <string>
+
+class cmTarget;
+class cmMessenger;
+
+class cmTargetPropertyComputer
+{
+public:
+ template <typename Target>
+ static const char* GetProperty(Target const* tgt, const std::string& prop,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context)
+ {
+ if (const char* loc = GetLocation(tgt, prop, messenger, context)) {
+ return loc;
+ }
+ if (cmSystemTools::GetFatalErrorOccured()) {
+ return CM_NULLPTR;
+ }
+ if (prop == "SOURCES") {
+ return GetSources(tgt, messenger, context);
+ }
+ return CM_NULLPTR;
+ }
+
+ static bool WhiteListedInterfaceProperty(const std::string& prop);
+
+ static bool PassesWhitelist(cmState::TargetType tgtType,
+ std::string const& prop, cmMessenger* messenger,
+ cmListFileBacktrace const& context);
+
+private:
+ static bool HandleLocationPropertyPolicy(std::string const& tgtName,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context);
+
+ template <typename Target>
+ static const char* ComputeLocationForBuild(Target const* tgt);
+ template <typename Target>
+ static const char* ComputeLocation(Target const* tgt,
+ std::string const& config);
+
+ template <typename Target>
+ static const char* GetLocation(Target const* tgt, std::string const& prop,
+ cmMessenger* messenger,
+ cmListFileBacktrace const& context)
+
+ {
+ // Watch for special "computed" properties that are dependent on
+ // other properties or variables. Always recompute them.
+ if (tgt->GetType() == cmState::EXECUTABLE ||
+ tgt->GetType() == cmState::STATIC_LIBRARY ||
+ tgt->GetType() == cmState::SHARED_LIBRARY ||
+ tgt->GetType() == cmState::MODULE_LIBRARY ||
+ tgt->GetType() == cmState::UNKNOWN_LIBRARY) {
+ static const std::string propLOCATION = "LOCATION";
+ if (prop == propLOCATION) {
+ if (!tgt->IsImported() &&
+ !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
+ context)) {
+ return CM_NULLPTR;
+ }
+ return ComputeLocationForBuild(tgt);
+ }
+
+ // Support "LOCATION_<CONFIG>".
+ else if (cmHasLiteralPrefix(prop, "LOCATION_")) {
+ if (!tgt->IsImported() &&
+ !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
+ context)) {
+ return CM_NULLPTR;
+ }
+ const char* configName = prop.c_str() + 9;
+ return ComputeLocation(tgt, configName);
+ }
+
+ // Support "<CONFIG>_LOCATION".
+ else if (cmHasLiteralSuffix(prop, "_LOCATION") &&
+ !cmHasLiteralPrefix(prop, "XCODE_ATTRIBUTE_")) {
+ std::string configName(prop.c_str(), prop.size() - 9);
+ if (configName != "IMPORTED") {
+ if (!tgt->IsImported() &&
+ !HandleLocationPropertyPolicy(tgt->GetName(), messenger,
+ context)) {
+ return CM_NULLPTR;
+ }
+ return ComputeLocation(tgt, configName);
+ }
+ }
+ }
+ return CM_NULLPTR;
+ }
+
+ template <typename Target>
+ static const char* GetSources(Target const* tgt, cmMessenger* messenger,
+ cmListFileBacktrace const& context);
+};
+
+#endif
diff --git a/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-LOCATION-stderr.txt b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-LOCATION-stderr.txt
index e4dbb71..d4e5b29 100644
--- a/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-LOCATION-stderr.txt
+++ b/Tests/RunCMake/GeneratorExpression/TARGET_PROPERTY-LOCATION-stderr.txt
@@ -1,4 +1,4 @@
-CMake Warning \(dev\) in CMakeLists.txt:
+CMake Warning \(dev\) at TARGET_PROPERTY-LOCATION.cmake:2 \(add_library\):
Policy CMP0026 is not set: Disallow use of the LOCATION target property.
Run "cmake --help-policy CMP0026" for policy details. Use the cmake_policy
command to set the policy and suppress this warning.
@@ -7,4 +7,6 @@ CMake Warning \(dev\) in CMakeLists.txt:
name directly with add_custom_command, or use the generator expression
\$<TARGET_FILE>, as appropriate.
+Call Stack \(most recent call first\):
+ CMakeLists.txt:3 \(include\)
This warning is for project developers. Use -Wno-dev to suppress it.
diff --git a/bootstrap b/bootstrap
index 9936365..d537211 100755
--- a/bootstrap
+++ b/bootstrap
@@ -311,6 +311,7 @@ CMAKE_CXX_SOURCES="\
cmBootstrapCommands2 \
cmCommandsForBootstrap \
cmTarget \
+ cmTargetPropertyComputer \
cmTest \
cmCustomCommand \
cmCustomCommandGenerator \