cmTargetPropCommandBase.cxx 4.29 KB
Newer Older
1 2
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
3 4 5
#include "cmTargetPropCommandBase.h"

#include "cmGlobalGenerator.h"
6
#include "cmMakefile.h"
7 8 9
#include "cmStateTypes.h"
#include "cmTarget.h"
#include "cmake.h"
10

11 12 13
bool cmTargetPropCommandBase::HandleArguments(
  std::vector<std::string> const& args, const std::string& prop,
  ArgumentFlags flags)
14
{
15
  if (args.size() < 2) {
16 17
    this->SetError("called with incorrect number of arguments");
    return false;
18
  }
19

20
  if (this->Makefile->IsAlias(args[0])) {
21 22
    this->SetError("can not be used on an ALIAS target.");
    return false;
23
  }
24
  // Lookup the target for which property-values are specified.
25
  this->Target =
26 27 28
    this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
      args[0]);
  if (!this->Target) {
29
    this->Target = this->Makefile->FindTargetToUse(args[0]);
30 31
  }
  if (!this->Target) {
32 33
    this->HandleMissingTarget(args[0]);
    return false;
34
  }
35 36 37 38 39 40
  if ((this->Target->GetType() != cmStateEnums::SHARED_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::MODULE_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
      (this->Target->GetType() != cmStateEnums::EXECUTABLE)) {
41 42
    this->SetError("called with non-compilable target type");
    return false;
43
  }
44

45
  bool system = false;
46 47
  unsigned int argIndex = 1;

48 49
  if ((flags & PROCESS_SYSTEM) && args[argIndex] == "SYSTEM") {
    if (args.size() < 3) {
50 51
      this->SetError("called with incorrect number of arguments");
      return false;
52
    }
53 54
    system = true;
    ++argIndex;
55
  }
56

57
  bool prepend = false;
58 59
  if ((flags & PROCESS_BEFORE) && args[argIndex] == "BEFORE") {
    if (args.size() < 3) {
60 61
      this->SetError("called with incorrect number of arguments");
      return false;
62
    }
63 64
    prepend = true;
    ++argIndex;
65
  }
66 67 68

  this->Property = prop;

69 70
  while (argIndex < args.size()) {
    if (!this->ProcessContentArgs(args, argIndex, prepend, system)) {
71 72
      return false;
    }
73
  }
74 75 76
  return true;
}

77 78 79
bool cmTargetPropCommandBase::ProcessContentArgs(
  std::vector<std::string> const& args, unsigned int& argIndex, bool prepend,
  bool system)
80
{
81
  std::string const& scope = args[argIndex];
82

83
  if (scope != "PUBLIC" && scope != "PRIVATE" && scope != "INTERFACE") {
84 85
    this->SetError("called with invalid arguments");
    return false;
86
  }
87

88 89
  ++argIndex;

90
  std::vector<std::string> content;
91

92 93 94
  for (unsigned int i = argIndex; i < args.size(); ++i, ++argIndex) {
    if (args[i] == "PUBLIC" || args[i] == "PRIVATE" ||
        args[i] == "INTERFACE") {
95
      break;
96
    }
97 98
    content.push_back(args[i]);
  }
99 100 101 102 103 104 105 106 107 108 109
  if (!content.empty()) {
    if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
        scope != "INTERFACE") {
      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;
    }
  }
110
  return this->PopulateTargetProperies(scope, content, prepend, system);
111 112
}

113 114 115
bool cmTargetPropCommandBase::PopulateTargetProperies(
  const std::string& scope, const std::vector<std::string>& content,
  bool prepend, bool system)
116
{
117 118 119
  if (content.empty()) {
    return true;
  }
120 121
  if (scope == "PRIVATE" || scope == "PUBLIC") {
    if (!this->HandleDirectContent(this->Target, content, prepend, system)) {
122
      return false;
123
    }
124 125
  }
  if (scope == "INTERFACE" || scope == "PUBLIC") {
126
    this->HandleInterfaceContent(this->Target, content, prepend, system);
127
  }
128
  return true;
129 130
}

131 132
void cmTargetPropCommandBase::HandleInterfaceContent(
  cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool)
133
{
134
  if (prepend) {
135
    const std::string propName = std::string("INTERFACE_") + this->Property;
136 137 138
    const char* propValue = tgt->GetProperty(propName);
    const std::string totalContent = this->Join(content) +
      (propValue ? std::string(";") + propValue : std::string());
139
    tgt->SetProperty(propName, totalContent.c_str());
140
  } else {
141
    tgt->AppendProperty("INTERFACE_" + this->Property,
142 143
                        this->Join(content).c_str());
  }
144
}