summaryrefslogtreecommitdiffstats
path: root/Source/cmTargetPropCommandBase.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmTargetPropCommandBase.cxx')
-rw-r--r--Source/cmTargetPropCommandBase.cxx191
1 files changed, 191 insertions, 0 deletions
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
new file mode 100644
index 0000000..8d2ff71
--- /dev/null
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -0,0 +1,191 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmTargetPropCommandBase.h"
+
+#include "cmExecutionStatus.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateTypes.h"
+#include "cmTarget.h"
+#include "cmValue.h"
+#include "cmake.h"
+
+cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status)
+ : Makefile(&status.GetMakefile())
+ , Status(status)
+{
+}
+
+void cmTargetPropCommandBase::SetError(std::string const& e)
+{
+ this->Status.SetError(e);
+}
+
+bool cmTargetPropCommandBase::HandleArguments(
+ std::vector<std::string> const& args, const std::string& prop,
+ unsigned int flags)
+{
+ if (args.size() < 2) {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+
+ if (this->Makefile->IsAlias(args[0])) {
+ this->SetError("can not be used on an ALIAS target.");
+ return false;
+ }
+ // Lookup the target for which property-values are specified.
+ this->Target =
+ this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
+ args[0]);
+ if (!this->Target) {
+ this->Target = this->Makefile->FindTargetToUse(args[0]);
+ }
+ if (!this->Target) {
+ this->HandleMissingTarget(args[0]);
+ return false;
+ }
+ const bool isRegularTarget =
+ (this->Target->GetType() == cmStateEnums::EXECUTABLE) ||
+ (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) ||
+ (this->Target->GetType() == cmStateEnums::UNKNOWN_LIBRARY);
+ const bool isCustomTarget = this->Target->GetType() == cmStateEnums::UTILITY;
+
+ if (prop == "SOURCES") {
+ if (!isRegularTarget && !isCustomTarget) {
+ this->SetError("called with non-compilable target type");
+ return false;
+ }
+ } else {
+ if (!isRegularTarget) {
+ this->SetError("called with non-compilable target type");
+ return false;
+ }
+ }
+
+ bool system = false;
+ unsigned int argIndex = 1;
+
+ if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") {
+ if (args.size() < 3) {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ system = true;
+ ++argIndex;
+ }
+
+ bool prepend = false;
+ if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") {
+ if (args.size() < 3) {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ prepend = true;
+ ++argIndex;
+ } else if ((flags & PROCESS_AFTER) && args[argIndex] == "AFTER") {
+ if (args.size() < 3) {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ prepend = false;
+ ++argIndex;
+ }
+
+ if ((flags & PROCESS_REUSE_FROM) && args[argIndex] == "REUSE_FROM") {
+ if (args.size() != 3) {
+ this->SetError("called with incorrect number of arguments");
+ return false;
+ }
+ ++argIndex;
+
+ this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM", args[argIndex]);
+ ++argIndex;
+ }
+
+ this->Property = prop;
+
+ while (argIndex < args.size()) {
+ if (!this->ProcessContentArgs(args, argIndex, prepend, system)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cmTargetPropCommandBase::ProcessContentArgs(
+ std::vector<std::string> const& args, unsigned int& argIndex, bool prepend,
+ bool system)
+{
+ std::string const& scope = args[argIndex];
+
+ if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") {
+ this->SetError("called with invalid arguments");
+ return false;
+ }
+
+ ++argIndex;
+
+ std::vector<std::string> content;
+
+ for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) {
+ if (args[i] == "PUBLIC" || args[i] == "PRIVATE" ||
+ args[i] == "INTERFACE") {
+ break;
+ }
+ content.push_back(args[i]);
+ }
+ if (!content.empty()) {
+ if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
+ scope != "INTERFACE" && this->Property != "SOURCES") {
+ this->SetError("may only set INTERFACE properties on INTERFACE targets");
+ return false;
+ }
+ if (this->Target->IsImported() && scope != "INTERFACE") {
+ this->SetError("may only set INTERFACE properties on IMPORTED targets");
+ return false;
+ }
+ if (this->Target->GetType() == cmStateEnums::UTILITY &&
+ scope != "PRIVATE") {
+ this->SetError("may only set PRIVATE properties on custom targets");
+ return false;
+ }
+ }
+ return this->PopulateTargetProperties(scope, content, prepend, system);
+}
+
+bool cmTargetPropCommandBase::PopulateTargetProperties(
+ const std::string& scope, const std::vector<std::string>& content,
+ bool prepend, bool system)
+{
+ if (content.empty()) {
+ return true;
+ }
+ if (scope == "PRIVATE" || scope == "PUBLIC") {
+ if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
+ return false;
+ }
+ }
+ if (scope == "INTERFACE" || scope == "PUBLIC") {
+ this->HandleInterfaceContent(this->Target, content, prepend, system);
+ }
+ return true;
+}
+
+void cmTargetPropCommandBase::HandleInterfaceContent(
+ cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool)
+{
+ if (prepend) {
+ const std::string propName = std::string("INTERFACE_") + this->Property;
+ cmValue propValue = tgt->GetProperty(propName);
+ const std::string totalContent =
+ this->Join(content) + (propValue ? (";" + *propValue) : std::string());
+ tgt->SetProperty(propName, totalContent);
+ } else {
+ tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content));
+ }
+}