Commit 188c762f authored by Brad King's avatar Brad King Committed by Kitware Robot

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
...
parents 9a2048f1 cef59bb8
Pipeline #31240 passed with stage
in 0 seconds
......@@ -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;
......
This diff is collapsed.
......@@ -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;
......
/* 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;
}
/* 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
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.
......@@ -311,6 +311,7 @@ CMAKE_CXX_SOURCES="\
cmBootstrapCommands2 \
cmCommandsForBootstrap \
cmTarget \
cmTargetPropertyComputer \
cmTest \
cmCustomCommand \
cmCustomCommandGenerator \
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment