blob: 83cc32b53cd6a4b38b4d73d86dcb696be9b3436e [file]
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#pragma once
#include "cmConfigure.h" // IWYU pragma: keep
#include <string>
#include <utility>
#include "cmStringAlgorithms.h"
#include "cmTargetTypes.h"
#include "cmValue.h"
class cmMakefile;
class cmTargetPropertyComputer
{
public:
template <typename Target>
static cmValue GetProperty(Target const* tgt, std::string const& prop,
cmMakefile const& mf)
{
if (cmValue loc = GetLocation(tgt, prop, mf)) {
return loc;
}
if (prop == "SOURCES") {
return GetSources(tgt);
}
return nullptr;
}
// True if `prop` is a *computed* location property for `type` -- i.e. one of
// LOCATION, LOCATION_<CONFIG>, or <CONFIG>_LOCATION on a target type that
// synthesizes a location. Reading one of these from a non-imported target
// is an error. Excludes IMPORTED_LOCATION and XCODE_ATTRIBUTE_*. If
// non-null, `config` is filled with the requested configuration ("" for
// plain LOCATION).
static bool IsComputedLocationProperty(cm::TargetType type,
std::string const& prop,
std::string* config = nullptr)
{
switch (type) {
case cm::TargetType::EXECUTABLE:
case cm::TargetType::STATIC_LIBRARY:
case cm::TargetType::SHARED_LIBRARY:
case cm::TargetType::MODULE_LIBRARY:
case cm::TargetType::UNKNOWN_LIBRARY:
break;
default:
return false;
}
if (prop == "LOCATION") {
if (config) {
config->clear();
}
return true;
}
if (cmHasLiteralPrefix(prop, "LOCATION_")) {
if (config) {
*config = prop.substr(9);
}
return true;
}
if (cmHasLiteralSuffix(prop, "_LOCATION") &&
!cmHasLiteralPrefix(prop, "XCODE_ATTRIBUTE_")) {
std::string c(prop.c_str(), prop.size() - 9);
if (c != "IMPORTED") {
if (config) {
*config = std::move(c);
}
return true;
}
}
return false;
}
private:
static void IssueLocationPropertyError(std::string const& tgtName,
cmMakefile const& mf);
template <typename Target>
static std::string const& ImportedLocation(Target const* tgt,
std::string const& config);
template <typename Target>
static cmValue GetLocation(Target const* tgt, std::string const& prop,
cmMakefile const& mf)
{
// Watch for special "computed" properties that are dependent on
// other properties or variables. Always recompute them.
std::string config;
if (!IsComputedLocationProperty(tgt->GetType(), prop, &config)) {
return nullptr;
}
if (!tgt->IsImported()) {
IssueLocationPropertyError(tgt->GetName(), mf);
return nullptr;
}
return cmValue(ImportedLocation(tgt, config));
}
template <typename Target>
static cmValue GetSources(Target const* tgt);
};