Merge topic 'extract-computed-target-properties'

cef59bb8 cmTarget: Implement GetProperty in terms of cmState::Snapshot
0d57b07a cmTarget: Group code for checking written properties together
c3fb0d95 cmTarget: Move sanity checks and computed property access to callers
fa9dbc56 cmGeneratorTarget: Implement cmTargetPropertyComputer interface
848ae2a6 cmTargetPropertyComputer: Template some methods on the Target
a0a720e6 cm{,Generator}Target: Add global generator accessors
637e3f3e cmTargetPropertyComputer: Unify whitelist handling from cmTarget
05251e6d cmTargetPropertyComputer: Move whitelist check from cmTarget
fbf1721c cmTargetPropertyComputer: Extract into new files
390a7d86 cmTargetPropertyComputer: Implement GetProperty without cmMakefile
e32a6bdd cmListFileBacktrace: Add a method to retrieve the Bottom of a snapshot
7863fba1 cmTarget: Extract GetLocation method
8096682e cmTarget: Extract GetSources method
7d57c1a2 cmTarget: Extract location computation methods
a55cac4b cmTarget: Split property computation into separate class
705fcf52 cmTarget: Move IMPORTED check to callers
...
This commit is contained in:
Brad King
2016-10-17 10:15:21 -04:00
committed by CMake Topic Stage
12 changed files with 493 additions and 291 deletions

View File

@@ -364,6 +364,8 @@ set(SRCS
cmSystemTools.h
cmTarget.cxx
cmTarget.h
cmTargetPropertyComputer.cxx
cmTargetPropertyComputer.h
cmTargetExport.h
cmTest.cxx
cmTest.h

View File

@@ -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();

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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.

View File

@@ -311,6 +311,7 @@ CMAKE_CXX_SOURCES="\
cmBootstrapCommands2 \
cmCommandsForBootstrap \
cmTarget \
cmTargetPropertyComputer \
cmTest \
cmCustomCommand \
cmCustomCommandGenerator \