mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-05 21:31:08 -06:00
Merge topic 'extract-computed-target-properties'
cef59bb8cmTarget: Implement GetProperty in terms of cmState::Snapshot0d57b07acmTarget: Group code for checking written properties togetherc3fb0d95cmTarget: Move sanity checks and computed property access to callersfa9dbc56cmGeneratorTarget: Implement cmTargetPropertyComputer interface848ae2a6cmTargetPropertyComputer: Template some methods on the Targeta0a720e6cm{,Generator}Target: Add global generator accessors637e3f3ecmTargetPropertyComputer: Unify whitelist handling from cmTarget05251e6dcmTargetPropertyComputer: Move whitelist check from cmTargetfbf1721ccmTargetPropertyComputer: Extract into new files390a7d86cmTargetPropertyComputer: Implement GetProperty without cmMakefilee32a6bddcmListFileBacktrace: Add a method to retrieve the Bottom of a snapshot7863fba1cmTarget: Extract GetLocation method8096682ecmTarget: Extract GetSources method7d57c1a2cmTarget: Extract location computation methodsa55cac4bcmTarget: Split property computation into separate class705fcf52cmTarget: Move IMPORTED check to callers ...
This commit is contained in:
@@ -364,6 +364,8 @@ set(SRCS
|
||||
cmSystemTools.h
|
||||
cmTarget.cxx
|
||||
cmTarget.h
|
||||
cmTargetPropertyComputer.cxx
|
||||
cmTargetPropertyComputer.h
|
||||
cmTargetExport.h
|
||||
cmTest.cxx
|
||||
cmTest.h
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
99
Source/cmTargetPropertyComputer.cxx
Normal file
99
Source/cmTargetPropertyComputer.cxx
Normal 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;
|
||||
}
|
||||
110
Source/cmTargetPropertyComputer.h
Normal file
110
Source/cmTargetPropertyComputer.h
Normal 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
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user